@dongdev/fca-unofficial 3.0.31 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +238 -398
  3. package/dist/cjs.cjs +9 -0
  4. package/dist/index.d.mts +1250 -0
  5. package/dist/index.d.ts +1250 -0
  6. package/dist/index.js +27772 -0
  7. package/dist/index.mjs +27735 -0
  8. package/docs/ARCHITECTURE.md +467 -0
  9. package/docs/DOCS.md +709 -0
  10. package/fca-config.example.json +33 -0
  11. package/package.json +32 -22
  12. package/test/fca.test.cjs +540 -0
  13. package/CHANGELOG.md +0 -296
  14. package/DOCS.md +0 -2712
  15. package/func/checkUpdate.js +0 -222
  16. package/func/logAdapter.js +0 -33
  17. package/func/logger.js +0 -48
  18. package/index.d.ts +0 -751
  19. package/index.js +0 -8
  20. package/module/config.js +0 -40
  21. package/module/login.js +0 -133
  22. package/module/loginHelper.js +0 -1296
  23. package/module/options.js +0 -44
  24. package/src/api/action/addExternalModule.js +0 -25
  25. package/src/api/action/changeAvatar.js +0 -137
  26. package/src/api/action/changeBio.js +0 -75
  27. package/src/api/action/enableAutoSaveAppState.js +0 -73
  28. package/src/api/action/getCurrentUserID.js +0 -7
  29. package/src/api/action/handleFriendRequest.js +0 -57
  30. package/src/api/action/logout.js +0 -76
  31. package/src/api/action/refreshFb_dtsg.js +0 -48
  32. package/src/api/action/setPostReaction.js +0 -106
  33. package/src/api/action/unfriend.js +0 -54
  34. package/src/api/http/httpGet.js +0 -46
  35. package/src/api/http/httpPost.js +0 -52
  36. package/src/api/http/postFormData.js +0 -47
  37. package/src/api/messaging/addUserToGroup.js +0 -68
  38. package/src/api/messaging/changeAdminStatus.js +0 -126
  39. package/src/api/messaging/changeArchivedStatus.js +0 -55
  40. package/src/api/messaging/changeBlockedStatus.js +0 -48
  41. package/src/api/messaging/changeGroupImage.js +0 -91
  42. package/src/api/messaging/changeNickname.js +0 -70
  43. package/src/api/messaging/changeThreadColor.js +0 -79
  44. package/src/api/messaging/changeThreadEmoji.js +0 -111
  45. package/src/api/messaging/createNewGroup.js +0 -88
  46. package/src/api/messaging/createPoll.js +0 -46
  47. package/src/api/messaging/createThemeAI.js +0 -98
  48. package/src/api/messaging/deleteMessage.js +0 -136
  49. package/src/api/messaging/deleteThread.js +0 -56
  50. package/src/api/messaging/editMessage.js +0 -68
  51. package/src/api/messaging/forwardAttachment.js +0 -57
  52. package/src/api/messaging/getEmojiUrl.js +0 -29
  53. package/src/api/messaging/getFriendsList.js +0 -82
  54. package/src/api/messaging/getMessage.js +0 -829
  55. package/src/api/messaging/getThemePictures.js +0 -62
  56. package/src/api/messaging/handleMessageRequest.js +0 -65
  57. package/src/api/messaging/markAsDelivered.js +0 -57
  58. package/src/api/messaging/markAsRead.js +0 -88
  59. package/src/api/messaging/markAsReadAll.js +0 -49
  60. package/src/api/messaging/markAsSeen.js +0 -61
  61. package/src/api/messaging/muteThread.js +0 -50
  62. package/src/api/messaging/removeUserFromGroup.js +0 -62
  63. package/src/api/messaging/resolvePhotoUrl.js +0 -43
  64. package/src/api/messaging/scheduler.js +0 -264
  65. package/src/api/messaging/searchForThread.js +0 -53
  66. package/src/api/messaging/sendMessage.js +0 -270
  67. package/src/api/messaging/sendTypingIndicator.js +0 -74
  68. package/src/api/messaging/setMessageReaction.js +0 -90
  69. package/src/api/messaging/setTitle.js +0 -124
  70. package/src/api/messaging/shareContact.js +0 -49
  71. package/src/api/messaging/threadColors.js +0 -128
  72. package/src/api/messaging/unsendMessage.js +0 -81
  73. package/src/api/messaging/uploadAttachment.js +0 -492
  74. package/src/api/socket/core/connectMqtt.js +0 -258
  75. package/src/api/socket/core/emitAuth.js +0 -103
  76. package/src/api/socket/core/getSeqID.js +0 -320
  77. package/src/api/socket/core/getTaskResponseData.js +0 -25
  78. package/src/api/socket/core/parseDelta.js +0 -377
  79. package/src/api/socket/detail/buildStream.js +0 -215
  80. package/src/api/socket/detail/constants.js +0 -28
  81. package/src/api/socket/listenMqtt.js +0 -377
  82. package/src/api/socket/middleware/index.js +0 -216
  83. package/src/api/threads/getThreadHistory.js +0 -664
  84. package/src/api/threads/getThreadInfo.js +0 -296
  85. package/src/api/threads/getThreadList.js +0 -293
  86. package/src/api/threads/getThreadPictures.js +0 -78
  87. package/src/api/users/getUserID.js +0 -65
  88. package/src/api/users/getUserInfo.js +0 -402
  89. package/src/api/users/getUserInfoV2.js +0 -134
  90. package/src/core/sendReqMqtt.js +0 -96
  91. package/src/database/helpers.js +0 -53
  92. package/src/database/models/index.js +0 -88
  93. package/src/database/models/thread.js +0 -50
  94. package/src/database/models/user.js +0 -46
  95. package/src/database/threadData.js +0 -94
  96. package/src/database/userData.js +0 -98
  97. package/src/remote/remoteClient.js +0 -123
  98. package/src/utils/broadcast.js +0 -51
  99. package/src/utils/client.js +0 -10
  100. package/src/utils/constants.js +0 -23
  101. package/src/utils/cookies.js +0 -68
  102. package/src/utils/format/attachment.js +0 -357
  103. package/src/utils/format/cookie.js +0 -9
  104. package/src/utils/format/date.js +0 -50
  105. package/src/utils/format/decode.js +0 -44
  106. package/src/utils/format/delta.js +0 -194
  107. package/src/utils/format/ids.js +0 -64
  108. package/src/utils/format/index.js +0 -64
  109. package/src/utils/format/message.js +0 -88
  110. package/src/utils/format/presence.js +0 -132
  111. package/src/utils/format/readTyp.js +0 -44
  112. package/src/utils/format/thread.js +0 -42
  113. package/src/utils/format/utils.js +0 -141
  114. package/src/utils/headers.js +0 -115
  115. package/src/utils/loginParser/autoLogin.js +0 -125
  116. package/src/utils/loginParser/helpers.js +0 -43
  117. package/src/utils/loginParser/index.js +0 -10
  118. package/src/utils/loginParser/parseAndCheckLogin.js +0 -220
  119. package/src/utils/loginParser/textUtils.js +0 -28
  120. package/src/utils/request/client.js +0 -26
  121. package/src/utils/request/config.js +0 -23
  122. package/src/utils/request/defaults.js +0 -46
  123. package/src/utils/request/helpers.js +0 -46
  124. package/src/utils/request/index.js +0 -17
  125. package/src/utils/request/methods.js +0 -163
  126. package/src/utils/request/proxy.js +0 -21
  127. package/src/utils/request/retry.js +0 -77
  128. package/src/utils/request/sanitize.js +0 -49
package/docs/DOCS.md ADDED
@@ -0,0 +1,709 @@
1
+ # @dongdev/fca-unofficial — Documentation
2
+
3
+ Comprehensive reference for **version 4.x**. The library is written in TypeScript; the published package ships `dist/` only. Source under `src/` is on [GitHub](https://github.com/dongp06/fca-unofficial).
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ 1. [Installation & Build](#1-installation--build)
10
+ 2. [Authentication](#2-authentication)
11
+ 3. [The Two API Layers](#3-the-two-api-layers)
12
+ 4. [Realtime — MQTT Listener](#4-realtime--mqtt-listener)
13
+ 5. [MessengerBot — Event-Driven Interface](#5-messengerbot--event-driven-interface)
14
+ 6. [Configuration File (`fca-config.json`)](#6-configuration-file-fca-configjson)
15
+ 7. [Thread Cache & Realtime Sync](#7-thread-cache--realtime-sync)
16
+ 8. [Database (Optional)](#8-database-optional)
17
+ 9. [API Reference — Messages](#9-api-reference--messages)
18
+ 10. [API Reference — Threads](#10-api-reference--threads)
19
+ 11. [API Reference — Users](#11-api-reference--users)
20
+ 12. [API Reference — Account](#12-api-reference--account)
21
+ 13. [API Reference — HTTP](#13-api-reference--http)
22
+ 14. [API Reference — Scheduler](#14-api-reference--scheduler)
23
+ 15. [Events Reference](#15-events-reference)
24
+ 16. [Exports Summary](#16-exports-summary)
25
+ 17. [Debugging MQTT](#17-debugging-mqtt)
26
+ 18. [Security & Ethics](#18-security--ethics)
27
+ 19. [License](#19-license)
28
+
29
+ ---
30
+
31
+ ## 1. Installation & Build
32
+
33
+ ```bash
34
+ npm install @dongdev/fca-unofficial@latest
35
+ ```
36
+
37
+ To work from source:
38
+
39
+ ```bash
40
+ git clone https://github.com/dongp06/fca-unofficial.git
41
+ cd fca-unofficial
42
+ npm install
43
+ npm run build
44
+ ```
45
+
46
+ Build output:
47
+
48
+ | File | Format |
49
+ |-------------------|-------------------|
50
+ | `dist/index.js` | CommonJS (CJS) |
51
+ | `dist/index.mjs` | ES Modules (ESM) |
52
+ | `dist/index.d.ts` | TypeScript types |
53
+
54
+ Additional scripts:
55
+
56
+ | Script | Purpose |
57
+ |-------------------|----------------------------------------|
58
+ | `npm run lint` | Run ESLint on the entire project |
59
+ | `npm run typecheck` | Type-check without emitting files |
60
+ | `npm test` | Run the test suite |
61
+
62
+ ---
63
+
64
+ ## 2. Authentication
65
+
66
+ ### 2.1. `require()` default = `login` (classic FCA / Mirai)
67
+
68
+ `package.json` points CommonJS `require` at `dist/cjs.cjs`, so the module itself **is** the `login` function (with all named exports copied onto it):
69
+
70
+ ```javascript
71
+ const login = require("@dongdev/fca-unofficial");
72
+
73
+ login({ appState: require("./appstate.json") }, (err, api) => {
74
+ if (err) return console.error(err);
75
+ api.setOptions({ listenEvents: true });
76
+ // api.getAppState(), api.listenMqtt(), …
77
+ });
78
+ ```
79
+
80
+ The callback receives **`api`** (flat legacy API), not `FcaContext`. For options + callback:
81
+
82
+ ```javascript
83
+ login({ appState: [...] }, { listenEvents: true }, (err, api) => { ... });
84
+ ```
85
+
86
+ ### 2.2. `login()` — Promise, returns `FcaContext`
87
+
88
+ ```typescript
89
+ import { login } from "@dongdev/fca-unofficial";
90
+
91
+ const ctx = await login(
92
+ { appState: require("./appstate.json") },
93
+ { listenEvents: true, selfListen: false }
94
+ );
95
+ const api = ctx.api;
96
+ ```
97
+
98
+ Use **`loginAsync`** if you need an explicit async function reference without overload resolution.
99
+
100
+ ### 2.3. Credential strategies
101
+
102
+ | Field | Description |
103
+ |--------------------|-----------------------------------------------------------------------------|
104
+ | `appState` | Array of cookie objects `{ key/name, value, domain, path }` exported from a browser extension or tool. **Recommended.** |
105
+ | `Cookie` | Raw cookie header string: `"c_user=...; xs=...; ..."`. |
106
+ | `email` + `password` | Web login credentials. Easily triggers checkpoints; **not recommended** for production bots. |
107
+
108
+ ### 2.4. `loginLegacy()` — callback with `FcaContext`
109
+
110
+ ```javascript
111
+ const { loginLegacy } = require("@dongdev/fca-unofficial");
112
+
113
+ loginLegacy({ appState: require("./appstate.json") }, (err, ctx) => {
114
+ if (err) return console.error(err);
115
+ const api = ctx.api;
116
+ // ...
117
+ });
118
+ ```
119
+
120
+ ### 2.5. Token-based login
121
+
122
+ `tokensViaAPI` and `loginViaAPI` authenticate through an external API server. Configure the `apiServer` and `credentials` fields in `fca-config.json`. See `src/core/auth.ts` for implementation details.
123
+
124
+ ### 2.6. Login options (`FcaOptions`)
125
+
126
+ | Option | Type | Default | Description |
127
+ |-------------------|-----------|-------------|------------------------------------------------|
128
+ | `logLevel` | `string` | `"info"` | `"silly"`, `"info"`, `"warn"`, `"error"`, `"silent"` |
129
+ | `listenEvents` | `boolean` | `false` | Receive thread-level events (not just messages) |
130
+ | `selfListen` | `boolean` | `false` | Receive messages sent by the logged-in user |
131
+ | `selfListenEvent` | `boolean` | `false` | Receive thread events triggered by self |
132
+ | `listenTyping` | `boolean` | `false` | Receive typing indicators |
133
+ | `updatePresence` | `boolean` | `false` | Receive online/offline presence updates |
134
+ | `forceLogin` | `boolean` | `false` | Force re-authentication |
135
+ | `autoMarkRead` | `boolean` | `false` | Automatically mark incoming messages as read |
136
+ | `autoReconnect` | `boolean` | `false` | Reconnect MQTT on disconnect |
137
+ | `online` | `boolean` | `false` | Appear as online to other users |
138
+ | `emitReady` | `boolean` | `false` | Emit `ready` event when MQTT connects |
139
+ | `userAgent` | `string` | Chrome UA | Custom User-Agent for HTTP requests |
140
+ | `proxy` | `string` | — | HTTP or SOCKS proxy URL |
141
+ | `pageID` | `string` | — | Act as a Facebook Page |
142
+
143
+ ---
144
+
145
+ ## 3. The Two API Layers
146
+
147
+ ### 3.1. Flat API (legacy-compatible)
148
+
149
+ `ctx.api` exposes all methods as top-level functions, matching the interface of earlier FCA forks:
150
+
151
+ ```javascript
152
+ api.sendMessage("Hello!", threadID);
153
+ api.getThreadInfo(threadID, callback);
154
+ api.getUserInfo(userIDs, callback);
155
+ api.setMessageReaction(reaction, messageID, callback);
156
+ api.listenMqtt(callback);
157
+ ```
158
+
159
+ Most methods accept an optional trailing `callback(err, result)`. When the callback is omitted, many methods return a `Promise`.
160
+
161
+ ### 3.2. Namespaced client facade
162
+
163
+ `createFcaClient` wraps the flat API into domain-grouped namespaces:
164
+
165
+ ```typescript
166
+ import { createFcaClient } from "@dongdev/fca-unofficial";
167
+
168
+ const client = createFcaClient(ctx.api);
169
+
170
+ // Messages
171
+ await client.messages.send("Hello!", threadID);
172
+ await client.messages.setReaction(":thumbsup:", messageID);
173
+
174
+ // Threads
175
+ const info = await client.threads.getInfo(threadID);
176
+ const list = await client.threads.getList(10, null, ["INBOX"]);
177
+
178
+ // Users
179
+ const userInfo = await client.users.getInfo(userID);
180
+
181
+ // Realtime
182
+ const emitter = client.realtime.listen();
183
+ emitter.on("message", (ev) => { /* ... */ });
184
+ ```
185
+
186
+ Available namespaces:
187
+
188
+ | Namespace | Flat API equivalents |
189
+ |--------------|-------------------------------------------------------------------------|
190
+ | `messages` | `sendMessage`, `editMessage`, `unsendMessage`, `deleteMessage`, `setMessageReaction`, `sendTypingIndicator`, `markAsRead`, `markAsDelivered`, `markAsSeen`, `markAsReadAll`, `uploadAttachment`, `forwardAttachment`, `shareContact`, `changeThreadColor`, `changeThreadEmoji` |
191
+ | `threads` | `getThreadInfo`, `getThreadList`, `getThreadHistory`, `getThreadPictures`, `searchForThread`, `createNewGroup`, `addUserToGroup`, `removeUserFromGroup`, `changeAdminStatus`, `changeGroupImage`, `changeNickname`, `setTitle`, `createPoll`, `createThemeAI`, `deleteThread`, `changeArchivedStatus`, `muteThread`, `handleMessageRequest`, `getThemePictures` |
192
+ | `users` | `getUserInfo`, `getUserInfoV2`, `getUserID`, `getFriendsList` |
193
+ | `account` | `getCurrentUserID`, `changeAvatar`, `changeBio`, `changeBlockedStatus`, `handleFriendRequest`, `unfriend`, `setPostReaction`, `refreshFb_dtsg`, `logout`, `addExternalModule`, `enableAutoSaveAppState` |
194
+ | `realtime` | `listenMqtt` |
195
+ | `http` | `httpGet`, `httpPost`, `postFormData` |
196
+ | `scheduler` | Scheduling utilities |
197
+
198
+ ---
199
+
200
+ ## 4. Realtime — MQTT Listener
201
+
202
+ The library maintains a persistent WebSocket connection to Facebook's MQTT broker for real-time event delivery.
203
+
204
+ ### EventEmitter style (no callback)
205
+
206
+ ```javascript
207
+ const mqtt = api.listenMqtt();
208
+
209
+ mqtt.on("message", (event) => {
210
+ // event.type: "message", "message_reply", "message_reaction",
211
+ // "message_unsend", "typ", "read", "presence",
212
+ // "event", "ready", etc.
213
+ console.log(event);
214
+ });
215
+
216
+ mqtt.on("error", (err) => {
217
+ console.error("MQTT error:", err);
218
+ });
219
+
220
+ // Stop listening
221
+ await mqtt.stopListeningAsync();
222
+ ```
223
+
224
+ ### Callback style (legacy)
225
+
226
+ ```javascript
227
+ api.listenMqtt((err, event) => {
228
+ if (err) return console.error(err);
229
+ // handle event
230
+ });
231
+ ```
232
+
233
+ ### Reconnection
234
+
235
+ When the connection drops, the library schedules a reconnect with debounce and jitter. The old MQTT client is fully cleaned up (`removeAllListeners` + `end`) before a new one is created. Configure the reconnect interval through `fca-config.json` → `mqtt.reconnectInterval`.
236
+
237
+ ---
238
+
239
+ ## 5. MessengerBot — Event-Driven Interface
240
+
241
+ `MessengerBot` provides a Discord.js / Telegraf-style experience with events, middleware, commands, and pattern matching.
242
+
243
+ ### 5.1. Creating a bot
244
+
245
+ ```typescript
246
+ import { createMessengerBot } from "@dongdev/fca-unofficial";
247
+
248
+ const bot = await createMessengerBot(
249
+ { Cookie: process.env.FCA_COOKIE },
250
+ {
251
+ listenEvents: true,
252
+ stopOnSignals: true,
253
+ commandPrefix: "/",
254
+ maxEventListeners: 64,
255
+ enableComposer: true
256
+ }
257
+ );
258
+ ```
259
+
260
+ ### 5.2. Bot options (`MessengerBotOptions`)
261
+
262
+ Extends `FcaOptions` with:
263
+
264
+ | Option | Type | Default | Description |
265
+ |---------------------|-----------|---------|-----------------------------------------------------------|
266
+ | `autoListen` | `boolean` | `true` | Start MQTT automatically after login |
267
+ | `enableComposer` | `boolean` | `true` | Enable the middleware pipeline (`use`, `command`, `hears`) |
268
+ | `commandPrefix` | `string` | `"/"` | Prefix for command matching |
269
+ | `stopOnSignals` | `boolean` | `false` | Auto-stop on `SIGINT` / `SIGTERM` |
270
+ | `maxEventListeners` | `number` | `64` | Max event listeners on the bot emitter (0 = unlimited) |
271
+
272
+ ### 5.3. Events
273
+
274
+ | Event name | When it fires |
275
+ |----------------------|-------------------------------------------------|
276
+ | `message` | Any message (including replies) |
277
+ | `messageCreate` | Alias for `message` |
278
+ | `message_reply` | A reply to an existing message |
279
+ | `messageReactionAdd` | A reaction added to a message |
280
+ | `messageDelete` | A message is unsent |
281
+ | `typingStart` | User starts typing |
282
+ | `typingStop` | User stops typing |
283
+ | `threadUpdate` | Thread metadata changed |
284
+ | `ready` / `shardReady` | MQTT connection established |
285
+ | `raw` / `update` | Every incoming MQTT delta (unfiltered) |
286
+ | `error` | Errors from the MQTT layer or composer |
287
+
288
+ Events are only emitted when there is at least one listener registered for that event name (memory optimization).
289
+
290
+ ### 5.4. Composer pipeline
291
+
292
+ The composer processes `message` and `message_reply` events through a Koa-style middleware chain.
293
+
294
+ **Global middleware:**
295
+
296
+ ```javascript
297
+ bot.use(async (ctx, next) => {
298
+ const start = Date.now();
299
+ await next();
300
+ console.log(`Processed in ${Date.now() - start}ms`);
301
+ });
302
+ ```
303
+
304
+ **Command handler:**
305
+
306
+ ```javascript
307
+ bot.command("help", async (ctx) => {
308
+ await ctx.replyAsync("Available commands: /ping, /help");
309
+ });
310
+ ```
311
+
312
+ Matches `{prefix}{name}` at the start of the message body (case-insensitive on the command name).
313
+
314
+ **Pattern matching:**
315
+
316
+ ```javascript
317
+ bot.hears(/order\s+#\d+/i, async (ctx) => {
318
+ await ctx.replyAsync("Looking up your order...");
319
+ });
320
+
321
+ bot.hears("thank", async (ctx) => {
322
+ await ctx.replyAsync("You're welcome!");
323
+ });
324
+ ```
325
+
326
+ `hears(string)` checks for a case-insensitive substring match. `hears(RegExp)` tests the full pattern.
327
+
328
+ **Error handler:**
329
+
330
+ ```javascript
331
+ bot.catch((err, ctx) => {
332
+ console.error("Middleware error in thread", ctx?.threadID, err);
333
+ });
334
+ ```
335
+
336
+ ### 5.5. `MessengerContext`
337
+
338
+ | Property / Method | Type / Return | Description |
339
+ |---------------------------|-----------------------|------------------------------------------|
340
+ | `ctx.text` | `string` | Trimmed message body |
341
+ | `ctx.body` | `string \| undefined` | Raw message body |
342
+ | `ctx.threadID` | `string` | Thread identifier |
343
+ | `ctx.senderID` | `string` | Sender's user ID |
344
+ | `ctx.messageID` | `string` | Message identifier |
345
+ | `ctx.event` | `MessageEvent` | Full event payload |
346
+ | `ctx.bot` | `MessengerBotLike` | Reference to the bot instance |
347
+ | `ctx.reply(payload, cb?)` | varies | Send a reply (callback-style) |
348
+ | `ctx.replyAsync(payload)` | `Promise` | Send a reply (promise-based) |
349
+
350
+ ### 5.6. Lifecycle
351
+
352
+ ```javascript
353
+ // Start listening + optional signal handling
354
+ await bot.launch({ stopOnSignals: true });
355
+
356
+ // Manual start (without signal handling)
357
+ bot.startListening();
358
+
359
+ // Graceful shutdown: stops MQTT, removes signal handlers, clears listeners
360
+ await bot.stop();
361
+ ```
362
+
363
+ ### 5.7. Accessing the client facade
364
+
365
+ ```javascript
366
+ const client = bot.client; // FcaClientFacade (lazy-initialized)
367
+ await client.messages.send("Hi from the facade!", threadID);
368
+ ```
369
+
370
+ ---
371
+
372
+ ## 6. Configuration File (`fca-config.json`)
373
+
374
+ Copy the example and customize:
375
+
376
+ ```bash
377
+ cp fca-config.example.json fca-config.json
378
+ ```
379
+
380
+ ### Block reference
381
+
382
+ #### `checkUpdate`
383
+
384
+ ```json
385
+ {
386
+ "checkUpdate": {
387
+ "enabled": true,
388
+ "install": false,
389
+ "notifyIfCurrent": false,
390
+ "packageName": "@dongdev/fca-unofficial",
391
+ "registryUrl": "https://registry.npmjs.org",
392
+ "timeoutMs": 10000
393
+ }
394
+ }
395
+ ```
396
+
397
+ | Field | Description |
398
+ |-------------------|---------------------------------------------------------|
399
+ | `enabled` | Check npm for a newer version on startup |
400
+ | `install` | Automatically install the update if found |
401
+ | `notifyIfCurrent` | Show a message even when already on the latest version |
402
+ | `timeoutMs` | Timeout for the registry HTTP request |
403
+
404
+ #### `mqtt`
405
+
406
+ ```json
407
+ {
408
+ "mqtt": {
409
+ "enabled": true,
410
+ "reconnectInterval": 3600
411
+ }
412
+ }
413
+ ```
414
+
415
+ | Field | Description |
416
+ |---------------------|---------------------------------------------------|
417
+ | `enabled` | Enable the MQTT realtime connection |
418
+ | `reconnectInterval` | Seconds between automatic reconnection cycles |
419
+
420
+ #### `credentials`
421
+
422
+ ```json
423
+ {
424
+ "credentials": {
425
+ "email": "",
426
+ "password": "",
427
+ "twofactor": ""
428
+ }
429
+ }
430
+ ```
431
+
432
+ Used by `autoLogin` and `loginViaAPI` for automatic session recovery.
433
+
434
+ #### `antiGetInfo`
435
+
436
+ ```json
437
+ {
438
+ "antiGetInfo": {
439
+ "AntiGetThreadInfo": false,
440
+ "AntiGetUserInfo": false
441
+ }
442
+ }
443
+ ```
444
+
445
+ When enabled, `getThreadInfo` and `getUserInfo` use SQLite-backed caching to reduce repeated GraphQL requests to Facebook.
446
+
447
+ #### `remoteControl`
448
+
449
+ ```json
450
+ {
451
+ "remoteControl": {
452
+ "enabled": false,
453
+ "url": "",
454
+ "token": "",
455
+ "autoReconnect": true
456
+ }
457
+ }
458
+ ```
459
+
460
+ Connects to an external WebSocket server for remote management. Emits `remoteConnected`, `remoteDisconnected`, `remoteStop`, `remoteBroadcast`, and `remoteMessage` events on the API emitter.
461
+
462
+ ---
463
+
464
+ ## 7. Thread Cache & Realtime Sync
465
+
466
+ When Sequelize and the `Thread` model are available, `getThreadInfo` reads from and writes to a local SQLite cache. Cached entries have a freshness window (~10 minutes) before a refetch is triggered.
467
+
468
+ **`attachThreadInfoRealtimeSync`** hooks into MQTT events of type `"event"` and:
469
+
470
+ - Updates or **invalidates** (`data: null`) the cache based on `logMessageType`.
471
+ - On participant subscribe/unsubscribe events, updates `participantIDs` and calls `getUserInfo` to refresh `userInfo` within the cached thread data.
472
+
473
+ This function is called automatically during the standard bootstrap. For custom login flows, you can invoke it manually:
474
+
475
+ ```typescript
476
+ import { attachThreadInfoRealtimeSync } from "@dongdev/fca-unofficial";
477
+
478
+ attachThreadInfoRealtimeSync(ctx, models, logger, api);
479
+ ```
480
+
481
+ ---
482
+
483
+ ## 8. Database (Optional)
484
+
485
+ The library optionally uses **SQLite + Sequelize** for local caching and analytics.
486
+
487
+ ### Models
488
+
489
+ | Model | Purpose |
490
+ |----------|-----------------------------------------------------------------|
491
+ | `Thread` | Caches thread info (JSON in `data` column), tracks `messageCount` |
492
+ | `User` | Caches user info |
493
+
494
+ When the database is not configured, cache features fall back to in-memory storage or are skipped entirely. The `Thread.messageCount` field is atomically incremented on each incoming message via `attachThreadUpdater`, enabling analytics like "most active threads" without impacting message processing latency.
495
+
496
+ ---
497
+
498
+ ## 9. API Reference — Messages
499
+
500
+ | Method | Description |
501
+ |---------------------------|-------------------------------------------------------|
502
+ | `sendMessage` | Send text, attachments, stickers, or mentions |
503
+ | `editMessage` | Edit an existing message |
504
+ | `unsendMessage` | Unsend (retract) a message |
505
+ | `deleteMessage` | Delete a message |
506
+ | `setMessageReaction` | Add or remove a reaction on a message |
507
+ | `sendTypingIndicator` | Show or hide the typing indicator in a thread |
508
+ | `markAsRead` | Mark specific messages as read |
509
+ | `markAsDelivered` | Mark messages as delivered |
510
+ | `markAsSeen` | Mark messages as seen |
511
+ | `markAsReadAll` | Mark all messages in all threads as read |
512
+ | `uploadAttachment` | Upload a file and get an attachment ID |
513
+ | `forwardAttachment` | Forward an existing attachment to another thread |
514
+ | `shareContact` | Share a contact card |
515
+ | `changeThreadColor` | Change the chat color theme of a thread |
516
+ | `changeThreadEmoji` | Change the quick-reaction emoji of a thread |
517
+ | `getEmojiUrl` | Resolve the image URL for a given emoji |
518
+ | `getMessage` | Fetch a specific message by ID |
519
+ | `resolvePhotoUrl` | Resolve the full-resolution URL of a photo attachment |
520
+ | `getThreadColors` | List all available thread color themes |
521
+
522
+ ---
523
+
524
+ ## 10. API Reference — Threads
525
+
526
+ | Method | Description |
527
+ |-------------------------|-------------------------------------------------------------|
528
+ | `getThreadInfo` | Get detailed info about a thread (participants, name, etc.) |
529
+ | `getThreadList` | List threads with pagination and folder filtering |
530
+ | `getThreadHistory` | Retrieve message history for a thread |
531
+ | `getThreadPictures` | Get shared photos in a thread |
532
+ | `getThemePictures` | Get theme-related pictures |
533
+ | `searchForThread` | Search threads by name or keyword |
534
+ | `createNewGroup` | Create a new group conversation |
535
+ | `addUserToGroup` | Add one or more users to a group |
536
+ | `removeUserFromGroup` | Remove a user from a group |
537
+ | `changeAdminStatus` | Promote or demote a group admin |
538
+ | `changeGroupImage` | Update the group's profile image |
539
+ | `changeNickname` | Set a participant's nickname in a thread |
540
+ | `setTitle` | Change the group title |
541
+ | `createPoll` | Create a poll in a thread |
542
+ | `createThemeAI` | Create an AI-generated theme |
543
+ | `deleteThread` | Delete a thread |
544
+ | `changeArchivedStatus` | Archive or unarchive a thread |
545
+ | `muteThread` | Mute or unmute notifications for a thread |
546
+ | `handleMessageRequest` | Accept or decline a message request |
547
+
548
+ ---
549
+
550
+ ## 11. API Reference — Users
551
+
552
+ | Method | Description |
553
+ |------------------|--------------------------------------------------------|
554
+ | `getUserInfo` | Get user info by ID(s) — supports batch requests |
555
+ | `getUserInfoV2` | Alternative user info endpoint |
556
+ | `getUserID` | Resolve a vanity URL or username to a user ID |
557
+ | `getFriendsList` | Get the authenticated user's friends list |
558
+
559
+ ---
560
+
561
+ ## 12. API Reference — Account
562
+
563
+ | Method | Description |
564
+ |---------------------------|------------------------------------------------------|
565
+ | `getCurrentUserID` | Get the logged-in user's Facebook ID |
566
+ | `changeAvatar` | Update the profile picture |
567
+ | `changeBio` | Update the profile bio |
568
+ | `changeBlockedStatus` | Block or unblock a user |
569
+ | `handleFriendRequest` | Accept, decline, or cancel a friend request |
570
+ | `unfriend` | Remove a user from the friends list |
571
+ | `setPostReaction` | React to a Facebook post |
572
+ | `refreshFb_dtsg` | Refresh the `fb_dtsg` security token |
573
+ | `logout` | End the session and invalidate cookies |
574
+ | `addExternalModule` | Register an external module on the API |
575
+ | `enableAutoSaveAppState` | Toggle automatic appState persistence |
576
+
577
+ ---
578
+
579
+ ## 13. API Reference — HTTP
580
+
581
+ Low-level HTTP utilities for making authenticated requests to Facebook's endpoints.
582
+
583
+ | Method | Description |
584
+ |----------------|-----------------------------------------------|
585
+ | `httpGet` | Authenticated GET request |
586
+ | `httpPost` | Authenticated POST request |
587
+ | `postFormData` | Authenticated multipart/form-data POST |
588
+
589
+ ---
590
+
591
+ ## 14. API Reference — Scheduler
592
+
593
+ The scheduler domain provides utilities for deferred and periodic task execution within the bot lifecycle.
594
+
595
+ ---
596
+
597
+ ## 15. Events Reference
598
+
599
+ ### MQTT events (`MqttEvent` union type)
600
+
601
+ | Type | Interface | Key fields |
602
+ |----------------------------|------------------------------|-----------------------------------------------------|
603
+ | `message` | `MessageEvent` | `threadID`, `senderID`, `messageID`, `body`, `attachments` |
604
+ | `message_reply` | `MessageEvent` | Same as `message`, triggered on reply |
605
+ | `message_reaction` | `ReactionEvent` | `messageID`, `reaction`, `userID` |
606
+ | `message_unsend` | `MessageUnsendEvent` | `messageID`, `senderID`, `deletionTimestamp` |
607
+ | `read` / `read_receipt` | `ReadEvent` | `reader` |
608
+ | `presence` | `PresenceEvent` | `userID`, `statuses` |
609
+ | `typ` | `TypingEvent` | `isTyping`, `from` |
610
+ | `friend_request_received` | `FriendRequestReceivedEvent` | `actorFbId` |
611
+ | `friend_request_cancel` | `FriendRequestCancelEvent` | `actorFbId` |
612
+ | `ready` | `ReadyEvent` | `error: null` |
613
+ | `event` | `ThreadEvent` | `logMessageType`, `logMessageData`, `logMessageBody`, `author` |
614
+ | `account_inactive` | `AccountInactiveEvent` | `reason`, `error` |
615
+ | `stop_listen` | `StopListenEvent` | `error` |
616
+
617
+ ### API emitter events (lifecycle)
618
+
619
+ | Event | Trigger |
620
+ |---------------------|------------------------------------------------|
621
+ | `sessionExpired` | The session cookie is no longer valid |
622
+ | `autoLoginSuccess` | Automatic re-login succeeded |
623
+ | `autoLoginFailed` | Automatic re-login failed |
624
+ | `checkpoint` | Facebook is requesting a security checkpoint |
625
+ | `checkpoint_282` | Checkpoint type 282 |
626
+ | `checkpoint_956` | Checkpoint type 956 |
627
+ | `loginBlocked` | Login was blocked by Facebook |
628
+ | `rateLimit` | Request was rate-limited |
629
+ | `networkError` | A network-level error occurred |
630
+ | `remoteConnected` | Connected to the remote control WebSocket |
631
+ | `remoteDisconnected`| Disconnected from the remote control WebSocket |
632
+ | `remoteStop` | Remote control issued a stop command |
633
+ | `remoteBroadcast` | Remote control broadcast message received |
634
+ | `remoteMessage` | Incoming remote control message |
635
+
636
+ ---
637
+
638
+ ## 16. Exports Summary
639
+
640
+ All public exports from `@dongdev/fca-unofficial`:
641
+
642
+ | Export | Category | Description |
643
+ |---------------------------------|----------------|---------------------------------------------------|
644
+ | `login` | Auth | Promise login **or** `login(cred, (err, api) => …)` / `login(cred, opts, cb)` (classic FCA) |
645
+ | `loginAsync` | Auth | Always `Promise<FcaContext>` (no callback overload) |
646
+ | `loginLegacy` | Auth | Callback receives `FcaContext` |
647
+ | `loginViaAPI` | Auth | Token-based login via external API |
648
+ | `tokensViaAPI` | Auth | Fetch tokens from external API |
649
+ | `normalizeCookieHeaderString` | Auth | Normalize a raw cookie string |
650
+ | `setJarFromPairs` | Auth | Populate a cookie jar from key-value pairs |
651
+ | `createDefaultContext` | Core | Create a blank `FcaContext` |
652
+ | `createFcaState` | Core | Create an initialized state object |
653
+ | `createApiFacade` | Core | Build the base API facade |
654
+ | `createRequestHelper` | Core | HTTP request utilities |
655
+ | `listenMqtt` | Core | MQTT helper function |
656
+ | `createAuthCore` | Core | Auth helper utilities |
657
+ | `defaultConfig` | Config | Default configuration values |
658
+ | `loadConfig` | Config | Load config from `fca-config.json` |
659
+ | `resolveConfig` | Config | Merge defaults with loaded config |
660
+ | `writeConfigTemplate` | Config | Write the example config to disk |
661
+ | `attachThreadInfoRealtimeSync` | Realtime/Cache | Sync thread cache from MQTT events |
662
+ | `checkForPackageUpdate` | Update | Check npm for a newer version |
663
+ | `runConfiguredUpdateCheck` | Update | Run update check based on config |
664
+ | `createFcaClient` | Client | Create the namespaced client facade |
665
+ | `MessengerBot` | Bot | Event-driven bot class |
666
+ | `createMessengerBot` | Bot | Factory function for `MessengerBot` |
667
+ | `MessengerContext` | Bot | Message context for composer handlers |
668
+ | `attachClientFacade` | Compat | Attach the client facade to an existing context |
669
+ | `createMessagesDomain` | Domain | Messages domain factory |
670
+ | `createThreadsDomain` | Domain | Threads domain factory |
671
+ | `createRealtimeDomain` | Domain | Realtime domain factory |
672
+ | `createUsersDomain` | Domain | Users domain factory |
673
+ | `createAccountDomain` | Domain | Account domain factory |
674
+ | `createHttpDomain` | Domain | HTTP domain factory |
675
+ | `createSchedulerDomain` | Domain | Scheduler domain factory |
676
+ | `export * from "./types"` | Types | All TypeScript type definitions |
677
+
678
+ ---
679
+
680
+ ## 17. Debugging MQTT
681
+
682
+ ### "No subscription existed"
683
+
684
+ This error was resolved internally by ensuring topic subscriptions complete before publishing the sync queue. If you see it, make sure you are using the latest version.
685
+
686
+ ### Reconnection issues
687
+
688
+ - `close`, `disconnect`, and `error` events on the MQTT client schedule a reconnect with debounce + jitter.
689
+ - The old client is fully torn down (`removeAllListeners()` + `end()`) before a new client is created, preventing ghost listeners and memory leaks.
690
+ - The `mqtt.reconnectInterval` config controls the periodic reconnection cycle (in seconds).
691
+
692
+ ### Logging
693
+
694
+ Set `logLevel: "silly"` in your login options to enable verbose logging of MQTT frames and HTTP requests.
695
+
696
+ ---
697
+
698
+ ## 18. Security & Ethics
699
+
700
+ - **Never commit** `appstate.json`, `cookie.txt`, or `fca-config.json` files containing passwords or tokens.
701
+ - **Rate-limit** your message sending to avoid triggering Facebook's spam detection.
702
+ - **Respect** Facebook / Meta's Terms of Service and applicable laws.
703
+ - **Do not** use this library for spamming, harassment, scraping personal data, or any other activity that harms users.
704
+
705
+ ---
706
+
707
+ ## 19. License
708
+
709
+ This project is licensed under the **Apache License, Version 2.0**. See the [LICENSE](../LICENSE) file for the full text.