@lazyneoaz/testfca 1.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.
- package/CHANGELOG.md +229 -0
- package/COOKIE_LOGIN.md +208 -0
- package/LICENSE +3 -0
- package/README.md +492 -0
- package/index.js +2 -0
- package/package.json +120 -0
- package/scripts/build-go.mjs +54 -0
- package/scripts/detect-platform.mjs +36 -0
- package/scripts/download-prebuilt.mjs +119 -0
- package/scripts/package.mjs +6 -0
- package/scripts/postinstall.mjs +113 -0
- package/src/apis/addExternalModule.js +24 -0
- package/src/apis/addUserToGroup.js +108 -0
- package/src/apis/changeAdminStatus.js +148 -0
- package/src/apis/changeArchivedStatus.js +61 -0
- package/src/apis/changeAvatar.js +103 -0
- package/src/apis/changeBio.js +69 -0
- package/src/apis/changeBlockedStatus.js +54 -0
- package/src/apis/changeGroupImage.js +136 -0
- package/src/apis/changeThreadColor.js +116 -0
- package/src/apis/changeThreadEmoji.js +53 -0
- package/src/apis/comment.js +207 -0
- package/src/apis/createAITheme.js +129 -0
- package/src/apis/createNewGroup.js +79 -0
- package/src/apis/createPoll.js +73 -0
- package/src/apis/deleteMessage.js +52 -0
- package/src/apis/deleteThread.js +52 -0
- package/src/apis/e2ee.js +170 -0
- package/src/apis/editMessage.js +78 -0
- package/src/apis/emoji.js +124 -0
- package/src/apis/fetchThemeData.js +82 -0
- package/src/apis/follow.js +81 -0
- package/src/apis/forwardMessage.js +52 -0
- package/src/apis/friend.js +243 -0
- package/src/apis/gcmember.js +122 -0
- package/src/apis/gcname.js +123 -0
- package/src/apis/gcrule.js +119 -0
- package/src/apis/getAccess.js +111 -0
- package/src/apis/getBotInfo.js +88 -0
- package/src/apis/getBotInitialData.js +43 -0
- package/src/apis/getFriendsList.js +79 -0
- package/src/apis/getMessage.js +423 -0
- package/src/apis/getTheme.js +95 -0
- package/src/apis/getThemeInfo.js +116 -0
- package/src/apis/getThreadHistory.js +239 -0
- package/src/apis/getThreadInfo.js +267 -0
- package/src/apis/getThreadList.js +232 -0
- package/src/apis/getThreadPictures.js +58 -0
- package/src/apis/getUserID.js +117 -0
- package/src/apis/getUserInfo.js +513 -0
- package/src/apis/getUserInfoV2.js +146 -0
- package/src/apis/handleMessageRequest.js +50 -0
- package/src/apis/httpGet.js +63 -0
- package/src/apis/httpPost.js +89 -0
- package/src/apis/httpPostFormData.js +69 -0
- package/src/apis/listenMqtt.js +1236 -0
- package/src/apis/listenSpeed.js +179 -0
- package/src/apis/logout.js +93 -0
- package/src/apis/markAsDelivered.js +47 -0
- package/src/apis/markAsRead.js +115 -0
- package/src/apis/markAsReadAll.js +40 -0
- package/src/apis/markAsSeen.js +70 -0
- package/src/apis/mqttDeltaValue.js +250 -0
- package/src/apis/muteThread.js +45 -0
- package/src/apis/nickname.js +132 -0
- package/src/apis/notes.js +163 -0
- package/src/apis/pinMessage.js +150 -0
- package/src/apis/produceMetaTheme.js +180 -0
- package/src/apis/realtime.js +182 -0
- package/src/apis/removeUserFromGroup.js +117 -0
- package/src/apis/resolvePhotoUrl.js +58 -0
- package/src/apis/searchForThread.js +154 -0
- package/src/apis/sendMessage.js +346 -0
- package/src/apis/sendMessageMqtt.js +248 -0
- package/src/apis/sendTypingIndicator.js +105 -0
- package/src/apis/setMessageReaction.js +38 -0
- package/src/apis/setMessageReactionMqtt.js +61 -0
- package/src/apis/setThreadTheme.js +260 -0
- package/src/apis/setThreadThemeMqtt.js +94 -0
- package/src/apis/share.js +107 -0
- package/src/apis/shareContact.js +66 -0
- package/src/apis/stickers.js +257 -0
- package/src/apis/story.js +181 -0
- package/src/apis/theme.js +233 -0
- package/src/apis/unfriend.js +47 -0
- package/src/apis/unsendMessage.js +25 -0
- package/src/database/appStateBackup.js +298 -0
- package/src/database/models/index.js +56 -0
- package/src/database/models/thread.js +31 -0
- package/src/database/models/user.js +32 -0
- package/src/database/threadData.js +101 -0
- package/src/database/userData.js +90 -0
- package/src/e2ee/bridge.js +275 -0
- package/src/e2ee/index.js +60 -0
- package/src/engine/client.js +95 -0
- package/src/engine/models/buildAPI.js +152 -0
- package/src/engine/models/loginHelper.js +574 -0
- package/src/engine/models/setOptions.js +88 -0
- package/src/types/index.d.ts +574 -0
- package/src/utils/antiSuspension.js +529 -0
- package/src/utils/auth-helpers.js +149 -0
- package/src/utils/autoReLogin.js +336 -0
- package/src/utils/axios.js +436 -0
- package/src/utils/cache.js +54 -0
- package/src/utils/clients.js +282 -0
- package/src/utils/constants.js +410 -0
- package/src/utils/formatters/data/formatAttachment.js +370 -0
- package/src/utils/formatters/data/formatDelta.js +109 -0
- package/src/utils/formatters/index.js +159 -0
- package/src/utils/formatters/value/formatCookie.js +91 -0
- package/src/utils/formatters/value/formatDate.js +36 -0
- package/src/utils/formatters/value/formatID.js +16 -0
- package/src/utils/formatters.js +1373 -0
- package/src/utils/headers.js +235 -0
- package/src/utils/index.js +153 -0
- package/src/utils/monitoring.js +333 -0
- package/src/utils/rateLimiter.js +319 -0
- package/src/utils/tokenRefresh.js +680 -0
- package/src/utils/user-agents.js +238 -0
- package/src/utils/validation.js +157 -0
package/README.md
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
# nkxfca
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@neoaz07/nkxfca)
|
|
4
|
+
[](https://www.npmjs.com/package/@neoaz07/nkxfca)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
|
|
8
|
+
**nkxfca** 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 **[NeoKEX](https://github.com/NeoKEX)**.
|
|
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
|
+
- **[Changelog](CHANGELOG.md)** — Version history and updates
|
|
19
|
+
- **[Examples](examples/)** — Code examples and usage patterns
|
|
20
|
+
|
|
21
|
+
### Support & Issues
|
|
22
|
+
|
|
23
|
+
- GitHub: [https://github.com/NeoKEX](https://github.com/NeoKEX)
|
|
24
|
+
- Issues: [https://github.com/NeoKEX/nkxfca/issues](https://github.com/NeoKEX/nkxfca/issues)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
**Authentication**
|
|
31
|
+
- Cookie array login (`appState`) — the safest method for long-running bots
|
|
32
|
+
- Email/password login with TOTP/2FA support
|
|
33
|
+
- Session fingerprint locking — User-Agent, Sec-Ch-Ua, locale, timezone locked per session to prevent detection
|
|
34
|
+
- AppState auto-backup and restore on restart
|
|
35
|
+
|
|
36
|
+
**Real-time Messaging**
|
|
37
|
+
- MQTT and HTTP messaging with automatic protocol fallback
|
|
38
|
+
- Send text, attachments, stickers, emoji, mentions, and location
|
|
39
|
+
- Message editing, unsend, forward, and delete
|
|
40
|
+
- Message reactions via HTTP and MQTT
|
|
41
|
+
- Pin/unpin messages, list pinned messages
|
|
42
|
+
|
|
43
|
+
**Anti-Suspension System**
|
|
44
|
+
- Circuit breaker — halts activity after repeated suspension signals, resumes after cooldown
|
|
45
|
+
- 60+ suspension signal patterns: checkpoints, spam flags, rate limits, identity verification, policy violations, session expiry, and more
|
|
46
|
+
- Adaptive per-thread delay that increases with session volume
|
|
47
|
+
- Hourly and daily message volume limits with automatic warning pauses
|
|
48
|
+
- Warmup mode for fresh sessions — gradually increases allowed message rate
|
|
49
|
+
- Humanized typing simulation before every send
|
|
50
|
+
- Randomized request intervals and jitter to avoid periodicity detection
|
|
51
|
+
- Session fingerprint locking to maintain consistent browser identity
|
|
52
|
+
- PostSafe guard: detects auth failures and checkpoint responses in real-time
|
|
53
|
+
- MQTT watchdog: detects stale connections and forces clean reconnect
|
|
54
|
+
|
|
55
|
+
**Stability & Reliability**
|
|
56
|
+
- MQTT auto-reconnect with exponential backoff and jitter
|
|
57
|
+
- Auto re-login using refreshed AppState when session expires
|
|
58
|
+
- TokenRefreshManager with randomized intervals to keep sessions alive
|
|
59
|
+
- Sliding-window rate limiter with per-endpoint tracking and accurate concurrency control
|
|
60
|
+
- SQLite-backed thread and user data cache for fast lookups
|
|
61
|
+
|
|
62
|
+
**Thread & Group Management**
|
|
63
|
+
- Get thread info, history, pictures, and lists
|
|
64
|
+
- Create groups, add/remove members, change admin status
|
|
65
|
+
- Update group image, name, color, emoji
|
|
66
|
+
- Archive, mute, delete threads
|
|
67
|
+
- Create polls, manage notes and rules
|
|
68
|
+
- Search threads by name, handle message requests
|
|
69
|
+
|
|
70
|
+
**User & Friends**
|
|
71
|
+
- Get user info (basic and extended), resolve user IDs
|
|
72
|
+
- Get full friends list, send/cancel friend requests, unfriend, block/unblock
|
|
73
|
+
|
|
74
|
+
**Social**
|
|
75
|
+
- Comment on posts, share posts, follow/unfollow users
|
|
76
|
+
|
|
77
|
+
**Themes & Stickers**
|
|
78
|
+
- Browse 90+ Messenger themes, apply themes via MQTT
|
|
79
|
+
- Generate AI-powered themes with text prompts
|
|
80
|
+
- Search stickers, browse packs, add packs, get AI stickers
|
|
81
|
+
|
|
82
|
+
**E2EE (Opt-In)**
|
|
83
|
+
- Application-layer end-to-end encryption for DMs using X25519 + HKDF + AES-256-GCM
|
|
84
|
+
|
|
85
|
+
**Monitoring**
|
|
86
|
+
- `api.getHealthStatus()` — MQTT status, token refresh stats, rate limiter metrics
|
|
87
|
+
- Built-in `ProductionMonitor` for request/error/performance telemetry
|
|
88
|
+
|
|
89
|
+
**Proxy Support**
|
|
90
|
+
- Full proxy support via the `proxy` login option
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Installation
|
|
95
|
+
|
|
96
|
+
> **Requirements:** Node.js v20.0.0 or higher
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm install @neoaz07/nkxfca
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Quick Start
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
const fs = require("fs");
|
|
108
|
+
const { login } = require("@neoaz07/nkxfca");
|
|
109
|
+
|
|
110
|
+
const appState = JSON.parse(fs.readFileSync("appstate.json", "utf8"));
|
|
111
|
+
|
|
112
|
+
login({ appState }, {
|
|
113
|
+
online: true,
|
|
114
|
+
listenEvents: true,
|
|
115
|
+
autoMarkRead: true,
|
|
116
|
+
autoReconnect: true,
|
|
117
|
+
simulateTyping: true
|
|
118
|
+
}, (err, api) => {
|
|
119
|
+
if (err) return console.error("Login error:", err);
|
|
120
|
+
|
|
121
|
+
console.log("Logged in as:", api.getCurrentUserID());
|
|
122
|
+
|
|
123
|
+
api.listenMqtt((err, event) => {
|
|
124
|
+
if (err || event.type !== "message" || !event.body) return;
|
|
125
|
+
|
|
126
|
+
if (event.body === "/ping") {
|
|
127
|
+
api.sendMessage("pong!", event.threadID);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Anti-Suspension Configuration
|
|
136
|
+
|
|
137
|
+
The anti-suspension system is active by default. You can tune it through login options:
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
login({ appState }, {
|
|
141
|
+
autoReconnect: true,
|
|
142
|
+
listenEvents: true,
|
|
143
|
+
autoMarkRead: true,
|
|
144
|
+
simulateTyping: true, // humanized typing delays before send
|
|
145
|
+
randomUserAgent: true, // rotate user agent on each session
|
|
146
|
+
persona: "desktop", // "desktop" or "android"
|
|
147
|
+
maxConcurrentRequests: 5, // max parallel HTTP requests
|
|
148
|
+
maxRequestsPerMinute: 50, // sliding-window rate cap
|
|
149
|
+
requestCooldownMs: 60000, // per-endpoint cooldown duration
|
|
150
|
+
errorCacheTtlMs: 300000 // how long to suppress repeated errors
|
|
151
|
+
}, (err, api) => {
|
|
152
|
+
if (err) throw err;
|
|
153
|
+
|
|
154
|
+
// Check anti-suspension and rate limiter status
|
|
155
|
+
console.log(api.getHealthStatus());
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Circuit Breaker
|
|
160
|
+
|
|
161
|
+
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.
|
|
162
|
+
|
|
163
|
+
You can also trip or reset it manually:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
const { globalAntiSuspension } = require("@neoaz07/nkxfca/src/utils/antiSuspension");
|
|
167
|
+
|
|
168
|
+
// Manually trip (e.g. after you detect a warning in a response)
|
|
169
|
+
globalAntiSuspension.tripCircuitBreaker("manual_pause", 30 * 60 * 1000); // 30 min
|
|
170
|
+
|
|
171
|
+
// Reset after you've resolved the issue
|
|
172
|
+
globalAntiSuspension.resetCircuitBreaker();
|
|
173
|
+
|
|
174
|
+
// Check status
|
|
175
|
+
console.log(globalAntiSuspension.getConfig());
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Warmup Mode
|
|
179
|
+
|
|
180
|
+
Use warmup mode when starting a fresh or recovered session:
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
const { globalAntiSuspension } = require("@neoaz07/nkxfca/src/utils/antiSuspension");
|
|
184
|
+
globalAntiSuspension.enableWarmup(); // limits to 25 msg/hour for 20 minutes
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## End-to-End Encryption for DMs (Opt-In)
|
|
190
|
+
|
|
191
|
+
Encrypt and decrypt message bodies in direct chats using X25519 + HKDF + AES-256-GCM.
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
api.e2ee.enable();
|
|
195
|
+
|
|
196
|
+
// Share your bot's public key with the peer
|
|
197
|
+
const botPubKey = api.e2ee.getPublicKey();
|
|
198
|
+
|
|
199
|
+
// Register the peer's public key for a DM thread
|
|
200
|
+
api.e2ee.setPeerKey(threadID, peerPublicKeyBase64);
|
|
201
|
+
|
|
202
|
+
// Messages to that thread are now auto-encrypted on send
|
|
203
|
+
// and auto-decrypted on receive
|
|
204
|
+
api.sendMessage("Top secret message", threadID);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Security Warning
|
|
210
|
+
|
|
211
|
+
`appstate.json` contains your Facebook session and must be treated like a password:
|
|
212
|
+
|
|
213
|
+
- **Never commit `appstate.json` to version control**
|
|
214
|
+
- **Never share your `appstate.json` publicly**
|
|
215
|
+
- Add it to `.gitignore`
|
|
216
|
+
- Use environment variables or a secrets manager in production
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Getting Started — Generate `appstate.json`
|
|
221
|
+
|
|
222
|
+
1. Install a cookie export extension:
|
|
223
|
+
- Chrome/Edge: **C3C FbState** or **CookieEditor**
|
|
224
|
+
- Firefox: **Cookie-Editor**
|
|
225
|
+
|
|
226
|
+
2. Log in to Facebook in your browser
|
|
227
|
+
|
|
228
|
+
3. Export cookies as JSON and save as `appstate.json`:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
[
|
|
232
|
+
{ "key": "c_user", "value": "your-user-id" },
|
|
233
|
+
{ "key": "xs", "value": "your-xs-value" }
|
|
234
|
+
]
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
4. Use in your bot:
|
|
238
|
+
|
|
239
|
+
```js
|
|
240
|
+
const { login } = require("@neoaz07/nkxfca");
|
|
241
|
+
const appState = require("./appstate.json");
|
|
242
|
+
login({ appState }, {}, (err, api) => { ... });
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
See **[COOKIE_LOGIN.md](COOKIE_LOGIN.md)** for more formats and troubleshooting.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Bot Example with Commands
|
|
250
|
+
|
|
251
|
+
```js
|
|
252
|
+
const fs = require("fs");
|
|
253
|
+
const path = require("path");
|
|
254
|
+
const { login } = require("@neoaz07/nkxfca");
|
|
255
|
+
|
|
256
|
+
const appState = JSON.parse(fs.readFileSync("appstate.json", "utf8"));
|
|
257
|
+
|
|
258
|
+
login({ appState }, {
|
|
259
|
+
online: true,
|
|
260
|
+
selfListen: false,
|
|
261
|
+
simulateTyping: true,
|
|
262
|
+
autoReconnect: true
|
|
263
|
+
}, async (err, api) => {
|
|
264
|
+
if (err) return console.error("Login error:", err);
|
|
265
|
+
|
|
266
|
+
console.log("Logged in as:", api.getCurrentUserID());
|
|
267
|
+
|
|
268
|
+
const commandsDir = path.join(__dirname, "commands");
|
|
269
|
+
const commands = new Map();
|
|
270
|
+
|
|
271
|
+
if (fs.existsSync(commandsDir)) {
|
|
272
|
+
for (const file of fs.readdirSync(commandsDir).filter(f => f.endsWith(".js"))) {
|
|
273
|
+
const cmd = require(path.join(commandsDir, file));
|
|
274
|
+
if (cmd.name && typeof cmd.execute === "function") {
|
|
275
|
+
commands.set(cmd.name, cmd);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
api.listenMqtt(async (err, event) => {
|
|
281
|
+
if (err || event.type !== "message" || !event.body) return;
|
|
282
|
+
|
|
283
|
+
const prefix = "/";
|
|
284
|
+
if (!event.body.startsWith(prefix)) return;
|
|
285
|
+
|
|
286
|
+
const args = event.body.slice(prefix.length).trim().split(/ +/);
|
|
287
|
+
const name = args.shift().toLowerCase();
|
|
288
|
+
const cmd = commands.get(name);
|
|
289
|
+
if (!cmd) return;
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
await cmd.execute({ api, event, args });
|
|
293
|
+
} catch (e) {
|
|
294
|
+
console.error(`Error in /${name}:`, e.message);
|
|
295
|
+
api.sendMessage("An error occurred.", event.threadID);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## AI Themes
|
|
304
|
+
|
|
305
|
+
```js
|
|
306
|
+
// Generate an AI theme from a text prompt
|
|
307
|
+
const aiThemes = await api.createAITheme("vibrant ocean sunset purple");
|
|
308
|
+
if (aiThemes && aiThemes.length > 0) {
|
|
309
|
+
await api.setThreadThemeMqtt(threadID, aiThemes[0].id);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Browse standard themes
|
|
313
|
+
const themes = await api.getTheme(threadID);
|
|
314
|
+
await api.setThreadThemeMqtt(threadID, themes[0].id);
|
|
315
|
+
|
|
316
|
+
// Check current theme
|
|
317
|
+
const info = await api.getThemeInfo(threadID);
|
|
318
|
+
console.log(info.color, info.emoji);
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## API Reference
|
|
324
|
+
|
|
325
|
+
### Authentication
|
|
326
|
+
| Method | Description |
|
|
327
|
+
|---|---|
|
|
328
|
+
| `login(credentials, options, callback)` | Log in and receive the API object |
|
|
329
|
+
| `api.logout()` | End the session |
|
|
330
|
+
| `api.getAppState()` | Get current session cookies |
|
|
331
|
+
| `api.getCurrentUserID()` | Get logged-in user ID |
|
|
332
|
+
|
|
333
|
+
### Messaging
|
|
334
|
+
| Method | Description |
|
|
335
|
+
|---|---|
|
|
336
|
+
| `api.sendMessage(msg, threadID)` | Send (HTTP + MQTT fallback) |
|
|
337
|
+
| `api.sendMessageMqtt(msg, threadID)` | Send over MQTT |
|
|
338
|
+
| `api.editMessage(text, messageID)` | Edit a message |
|
|
339
|
+
| `api.unsendMessage(messageID, threadID)` | Retract a message |
|
|
340
|
+
| `api.forwardMessage(messageID, threadID)` | Forward a message |
|
|
341
|
+
| `api.deleteMessage(messageIDs)` | Delete locally |
|
|
342
|
+
| `api.shareContact(senderID, threadID)` | Share a contact card |
|
|
343
|
+
|
|
344
|
+
### Reactions & Status
|
|
345
|
+
| Method | Description |
|
|
346
|
+
|---|---|
|
|
347
|
+
| `api.setMessageReaction(reaction, messageID)` | React via HTTP |
|
|
348
|
+
| `api.setMessageReactionMqtt(reaction, messageID, threadID)` | React via MQTT |
|
|
349
|
+
| `api.sendTypingIndicator(isTyping, threadID)` | Show/hide typing |
|
|
350
|
+
| `api.markAsRead(threadID)` | Mark thread as read |
|
|
351
|
+
| `api.markAsReadAll()` | Mark all threads as read |
|
|
352
|
+
| `api.markAsSeen()` | Mark as seen |
|
|
353
|
+
| `api.markAsDelivered(threadID, messageID)` | Mark as delivered |
|
|
354
|
+
|
|
355
|
+
### Threads
|
|
356
|
+
| Method | Description |
|
|
357
|
+
|---|---|
|
|
358
|
+
| `api.getThreadInfo(threadID)` | Thread metadata |
|
|
359
|
+
| `api.getThreadList(limit, timestamp, tags)` | List threads |
|
|
360
|
+
| `api.getThreadHistory(threadID, amount, timestamp)` | Message history |
|
|
361
|
+
| `api.getThreadPictures(threadID, offset, limit)` | Thread images |
|
|
362
|
+
| `api.searchForThread(name)` | Search by name |
|
|
363
|
+
| `api.createNewGroup(participantIDs, name?)` | Create group |
|
|
364
|
+
| `api.deleteThread(threadID)` | Delete thread |
|
|
365
|
+
| `api.muteThread(threadID, muteSeconds)` | Mute thread |
|
|
366
|
+
| `api.changeArchivedStatus(threadID, archive)` | Archive/unarchive |
|
|
367
|
+
| `api.pinMessage(action, threadID, messageID?)` | Pin/unpin/list |
|
|
368
|
+
| `api.createPoll(title, threadID, options?)` | Create poll |
|
|
369
|
+
| `api.handleMessageRequest(threadID, accept)` | Accept/decline |
|
|
370
|
+
|
|
371
|
+
### Group Admin
|
|
372
|
+
| Method | Description |
|
|
373
|
+
|---|---|
|
|
374
|
+
| `api.addUserToGroup(userID, threadID)` | Add member |
|
|
375
|
+
| `api.removeUserFromGroup(userID, threadID)` | Remove member |
|
|
376
|
+
| `api.changeAdminStatus(threadID, userID, isAdmin)` | Promote/demote |
|
|
377
|
+
| `api.changeGroupImage(image, threadID)` | Group photo |
|
|
378
|
+
| `api.gcname(name, threadID)` | Rename group |
|
|
379
|
+
|
|
380
|
+
### Users
|
|
381
|
+
| Method | Description |
|
|
382
|
+
|---|---|
|
|
383
|
+
| `api.getUserInfo(id)` | Basic user info |
|
|
384
|
+
| `api.getUserInfoV2(id)` | Extended user info |
|
|
385
|
+
| `api.getUserID(name)` | Resolve name to ID |
|
|
386
|
+
| `api.getFriendsList()` | Friends list |
|
|
387
|
+
| `api.getBotInfo()` | Bot account info |
|
|
388
|
+
|
|
389
|
+
### Themes & Customization
|
|
390
|
+
| Method | Description |
|
|
391
|
+
|---|---|
|
|
392
|
+
| `api.getTheme(threadID)` | List available themes |
|
|
393
|
+
| `api.getThemeInfo(threadID)` | Current theme |
|
|
394
|
+
| `api.setThreadThemeMqtt(threadID, themeID)` | Apply theme |
|
|
395
|
+
| `api.createAITheme(prompt)` | AI theme |
|
|
396
|
+
| `api.changeThreadColor(color, threadID)` | Thread color |
|
|
397
|
+
| `api.changeThreadEmoji(emoji, threadID)` | Thread emoji |
|
|
398
|
+
| `api.nickname(nickname, threadID, participantID)` | Set nickname |
|
|
399
|
+
| `api.emoji(emoji, threadID)` | Thread emoji shorthand |
|
|
400
|
+
|
|
401
|
+
### Stickers
|
|
402
|
+
| Method | Description |
|
|
403
|
+
|---|---|
|
|
404
|
+
| `api.stickers.search(query)` | Search stickers |
|
|
405
|
+
| `api.stickers.listPacks()` | Installed packs |
|
|
406
|
+
| `api.stickers.getStorePacks()` | Sticker store |
|
|
407
|
+
| `api.stickers.addPack(packID)` | Add pack |
|
|
408
|
+
| `api.stickers.getStickersInPack(packID)` | Stickers in pack |
|
|
409
|
+
| `api.stickers.getAiStickers(options?)` | AI stickers |
|
|
410
|
+
|
|
411
|
+
### E2EE
|
|
412
|
+
| Method | Description |
|
|
413
|
+
|---|---|
|
|
414
|
+
| `api.e2ee.enable()` | Enable E2EE |
|
|
415
|
+
| `api.e2ee.disable()` | Disable E2EE |
|
|
416
|
+
| `api.e2ee.getPublicKey()` | Get public key |
|
|
417
|
+
| `api.e2ee.setPeerKey(threadID, key)` | Set peer key |
|
|
418
|
+
| `api.e2ee.hasPeer(threadID)` | Has peer key |
|
|
419
|
+
| `api.e2ee.clearPeerKey(threadID)` | Remove peer key |
|
|
420
|
+
|
|
421
|
+
### Social
|
|
422
|
+
| Method | Description |
|
|
423
|
+
|---|---|
|
|
424
|
+
| `api.comment(msg, postID)` | Comment on post |
|
|
425
|
+
| `api.share(postID)` | Share post |
|
|
426
|
+
| `api.follow(userID, follow)` | Follow/unfollow |
|
|
427
|
+
| `api.unfriend(userID)` | Unfriend |
|
|
428
|
+
| `api.changeBlockedStatus(userID, block)` | Block/unblock |
|
|
429
|
+
|
|
430
|
+
### Health
|
|
431
|
+
| Method | Description |
|
|
432
|
+
|---|---|
|
|
433
|
+
| `api.getHealthStatus()` | MQTT, token, rate limiter stats |
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Login Options
|
|
438
|
+
|
|
439
|
+
| Option | Type | Default | Description |
|
|
440
|
+
|---|---|---|---|
|
|
441
|
+
| `online` | `boolean` | `true` | Appear online |
|
|
442
|
+
| `selfListen` | `boolean` | `false` | Receive own messages |
|
|
443
|
+
| `listenEvents` | `boolean` | `true` | Receive thread events |
|
|
444
|
+
| `listenTyping` | `boolean` | `false` | Receive typing events |
|
|
445
|
+
| `updatePresence` | `boolean` | `false` | Broadcast presence |
|
|
446
|
+
| `autoMarkDelivery` | `boolean` | `false` | Auto-mark delivered |
|
|
447
|
+
| `autoMarkRead` | `boolean` | `true` | Auto-mark read |
|
|
448
|
+
| `autoReconnect` | `boolean` | `true` | MQTT auto-reconnect |
|
|
449
|
+
| `simulateTyping` | `boolean` | `true` | Humanized typing delays |
|
|
450
|
+
| `randomUserAgent` | `boolean` | `false` | Random User-Agent |
|
|
451
|
+
| `persona` | `"desktop"\|"android"` | `"desktop"` | Browser persona |
|
|
452
|
+
| `proxy` | `string` | — | Proxy URL |
|
|
453
|
+
| `forceLogin` | `boolean` | `false` | Force fresh login |
|
|
454
|
+
| `maxConcurrentRequests` | `number` | `5` | Max parallel requests |
|
|
455
|
+
| `maxRequestsPerMinute` | `number` | `50` | Rate cap per minute |
|
|
456
|
+
| `requestCooldownMs` | `number` | `60000` | Endpoint cooldown |
|
|
457
|
+
| `errorCacheTtlMs` | `number` | `300000` | Error suppression TTL |
|
|
458
|
+
| `stealthMode` | `boolean` | `false` | Extra stealth headers |
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## Examples
|
|
463
|
+
|
|
464
|
+
See the **[examples/](examples/)** directory:
|
|
465
|
+
- `login-with-cookies.js` — Cookie-based authentication guide
|
|
466
|
+
- `verify.js` — Verify the library loads correctly
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## Credits
|
|
471
|
+
|
|
472
|
+
- **Developed and maintained by [NeoKEX](https://github.com/NeoKEX)**
|
|
473
|
+
- **NeoKEX Team** — development, maintenance, and feature contributions
|
|
474
|
+
- **Inspired by ws3-fca** — by @NethWs3Dev and @CommunityExocore
|
|
475
|
+
|
|
476
|
+
> Copyright (c) 2026 NeoKEX
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## License
|
|
481
|
+
|
|
482
|
+
**MIT** — Free to use, modify, and distribute. Attribution appreciated.
|
|
483
|
+
|
|
484
|
+
See [LICENSE](LICENSE) for full license text.
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## Links
|
|
489
|
+
|
|
490
|
+
- **npm:** [https://www.npmjs.com/package/@neoaz07/nkxfca](https://www.npmjs.com/package/@neoaz07/nkxfca)
|
|
491
|
+
- **GitHub:** [https://github.com/NeoKEX](https://github.com/NeoKEX)
|
|
492
|
+
- **Issues:** [https://github.com/NeoKEX/nkxfca/issues](https://github.com/NeoKEX/nkxfca/issues)
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lazyneoaz/testfca",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"description": "Advanced Facebook Chat API client for building Messenger bots — supports real-time messaging, thread management, MQTT, session stability, anti-automation protection, and real E2EE via Signal Protocol.",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"types": "src/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"index.js",
|
|
13
|
+
"src/",
|
|
14
|
+
"scripts/",
|
|
15
|
+
"prebuilt/",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"COOKIE_LOGIN.md"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/NeoKEX/nkxfca.git"
|
|
27
|
+
},
|
|
28
|
+
"author": "NeoKEX",
|
|
29
|
+
"contributors": [
|
|
30
|
+
"NeoKEX Team"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/NeoKEX/nkxfca/issues"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/NeoKEX/nkxfca#readme",
|
|
37
|
+
"keywords": [
|
|
38
|
+
"facebook",
|
|
39
|
+
"messenger",
|
|
40
|
+
"chat",
|
|
41
|
+
"bot",
|
|
42
|
+
"fca",
|
|
43
|
+
"mqtt",
|
|
44
|
+
"messaging",
|
|
45
|
+
"api",
|
|
46
|
+
"automation",
|
|
47
|
+
"facebook-chat-api",
|
|
48
|
+
"nkxfca",
|
|
49
|
+
"neoaz07",
|
|
50
|
+
"e2ee",
|
|
51
|
+
"signal-protocol",
|
|
52
|
+
"anti-suspension"
|
|
53
|
+
],
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"axios": "^1.9.0",
|
|
56
|
+
"axios-cookiejar-support": "^4.0.7",
|
|
57
|
+
"bluebird": "^3.7.2",
|
|
58
|
+
"cheerio": "^1.0.0",
|
|
59
|
+
"deepdash": "^5.3.9",
|
|
60
|
+
"duplexify": "^4.1.3",
|
|
61
|
+
"form-data": "^4.0.4",
|
|
62
|
+
"https-proxy-agent": "^7.0.6",
|
|
63
|
+
"jsonpath-plus": "^10.3.0",
|
|
64
|
+
"koffi": "^3.0.2",
|
|
65
|
+
"lodash": "^4.17.21",
|
|
66
|
+
"mqtt": "^4.3.8",
|
|
67
|
+
"node-cron": "^3.0.3",
|
|
68
|
+
"npmlog": "^7.0.1",
|
|
69
|
+
"sequelize": "^6.37.5",
|
|
70
|
+
"sqlite3": "^6.0.1",
|
|
71
|
+
"totp-generator": "^2.0.1",
|
|
72
|
+
"tough-cookie": "^5.1.2",
|
|
73
|
+
"undici": "^7.8.0",
|
|
74
|
+
"uuid": "^11.1.0",
|
|
75
|
+
"websocket-stream": "^5.5.2",
|
|
76
|
+
"ws": "^8.18.2"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@types/node": "^22.15.17",
|
|
80
|
+
"eslint": "^9.26.0",
|
|
81
|
+
"mocha": "^11.3.0",
|
|
82
|
+
"prettier": "^3.5.3",
|
|
83
|
+
"ts-node": "^10.9.2",
|
|
84
|
+
"typescript": "^5.8.3"
|
|
85
|
+
},
|
|
86
|
+
"engines": {
|
|
87
|
+
"node": ">=22.12.0"
|
|
88
|
+
},
|
|
89
|
+
"scripts": {
|
|
90
|
+
"prepack": "echo 'Preparing package for npm...'",
|
|
91
|
+
"test": "echo 'No tests configured yet'",
|
|
92
|
+
"lint": "eslint src/",
|
|
93
|
+
"format": "prettier --write src/**/*.js",
|
|
94
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
95
|
+
"build:go": "node scripts/build-go.mjs",
|
|
96
|
+
"validate": "npm pack --dry-run"
|
|
97
|
+
},
|
|
98
|
+
"overrides": {
|
|
99
|
+
"undici": "^7.8.0",
|
|
100
|
+
"ws": "^8.18.2",
|
|
101
|
+
"tough-cookie": "^5.1.2",
|
|
102
|
+
"glob": "^11.0.2",
|
|
103
|
+
"prebuild-install": "^7.1.3",
|
|
104
|
+
"npmlog": "^7.0.1",
|
|
105
|
+
"are-we-there-yet": "^4.0.2",
|
|
106
|
+
"gauge": "^5.0.2",
|
|
107
|
+
"serialize-javascript": "^6.0.2",
|
|
108
|
+
"cacache": "^18.0.4",
|
|
109
|
+
"make-fetch-happen": "^13.0.3",
|
|
110
|
+
"@tootallnate/once": "^3.0.1",
|
|
111
|
+
"mocha": {
|
|
112
|
+
"serialize-javascript": "^6.0.2",
|
|
113
|
+
"debug": "^4.4.0",
|
|
114
|
+
"diff": "^7.0.0",
|
|
115
|
+
"js-yaml": "^4.1.0",
|
|
116
|
+
"minimatch": "^10.0.1",
|
|
117
|
+
"glob": "^11.0.2"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
import { detectPlatform } from "./detect-platform.mjs";
|
|
7
|
+
import { packageJson } from "./package.mjs";
|
|
8
|
+
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const { ext } = detectPlatform();
|
|
11
|
+
const { name } = packageJson;
|
|
12
|
+
const bridgeDir = join(__dirname, "..", "bridge-e2ee", "bridge-go");
|
|
13
|
+
const vendorDir = join(bridgeDir, "vendor");
|
|
14
|
+
const hasVendor = existsSync(vendorDir);
|
|
15
|
+
|
|
16
|
+
function runGo(args) {
|
|
17
|
+
const res = spawnSync(process.env.GO_BIN || "go", args, {
|
|
18
|
+
cwd: bridgeDir,
|
|
19
|
+
stdio: "inherit",
|
|
20
|
+
env: { ...process.env, CGO_ENABLED: "1" },
|
|
21
|
+
});
|
|
22
|
+
if (res.error) {
|
|
23
|
+
console.error(`[${name}] Failed to spawn Go: ${res.error.message}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
if (res.status !== 0) process.exit(res.status || 1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const buildDir = join(__dirname, "..", "build");
|
|
30
|
+
if (!existsSync(buildDir)) mkdirSync(buildDir, { recursive: true });
|
|
31
|
+
|
|
32
|
+
// Skip mod tidy when vendor directory is present — tidy can break vendor/go.mod consistency
|
|
33
|
+
// and would overwrite the patched prekeys.go with the unpatched upstream version.
|
|
34
|
+
if (!hasVendor) {
|
|
35
|
+
console.log(`[${name}] Tidying Go modules...`);
|
|
36
|
+
runGo(["mod", "tidy"]);
|
|
37
|
+
} else {
|
|
38
|
+
console.log(`[${name}] Vendor directory present — skipping mod tidy to preserve patches.`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const buildArgs = [
|
|
42
|
+
"build",
|
|
43
|
+
...(hasVendor ? ["-mod=vendor"] : []),
|
|
44
|
+
"-buildmode=c-shared",
|
|
45
|
+
"-ldflags=-s -w",
|
|
46
|
+
"-o",
|
|
47
|
+
join("..", "..", "build", `messagix.${ext}`),
|
|
48
|
+
".",
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
console.log(`[${name}] Building native library (release mode)...`);
|
|
52
|
+
runGo(buildArgs);
|
|
53
|
+
|
|
54
|
+
console.log(`[${name}] Built native: build/messagix.${ext}`);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
export function detectPlatform() {
|
|
4
|
+
const { platform } = process;
|
|
5
|
+
const { arch } = process;
|
|
6
|
+
const isMusl = detectMusl();
|
|
7
|
+
|
|
8
|
+
const libc = platform === "linux" ? (isMusl ? "musl" : "gnu") : "";
|
|
9
|
+
const triplet = platform === "linux" ? `${platform}-${arch}-${libc}` : `${platform}-${arch}`;
|
|
10
|
+
|
|
11
|
+
const ext = platform === "win32" ? "dll" : platform === "darwin" ? "dylib" : "so";
|
|
12
|
+
|
|
13
|
+
return { platform, arch, libc, triplet, ext };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function detectMusl() {
|
|
17
|
+
try {
|
|
18
|
+
if (process.platform !== "linux") return false;
|
|
19
|
+
if (process.report && typeof process.report.getReport === "function") {
|
|
20
|
+
const rep = process.report.getReport();
|
|
21
|
+
const glibc = rep.header && rep.header.glibcVersionRuntime;
|
|
22
|
+
return !glibc;
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
//
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const out = execSync("ldd --version 2>&1 || true", { encoding: "utf8" });
|
|
29
|
+
return /musl/i.test(out);
|
|
30
|
+
} catch {
|
|
31
|
+
//
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default detectPlatform;
|