@dongdev/fca-unofficial 3.0.30 → 4.0.0

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