fca-anodite
v1.0.0
Published
npm wrapper for the botws FCA private WebSocket connection — drop-in compatible with / fca-unofficial API surface
Maintainers
Readme
botws-fca
An npm wrapper for the botws private WebSocket FCA connection — fully drop-in compatible with the @tas33n/ws3-fca / fca-unofficial API surface.
All method names (sendMessage, getThreadInfo, listen, etc.) are identical to ws3-fca, so any bot already built on that interface needs zero changes to its command or event handlers.
How it works
Instead of speaking to Facebook's servers directly, this package routes every API call through the khotools.com private WebSocket server — the same backend used by the botws bot framework.
Your bot ──► botws-fca ──► WebSocket ──► khotools.com ──► FacebookRequirements
- Node.js 18 or newer
- A Facebook session cookie (
c_user+xsat minimum) - A Khotools API key — register for free at https://khotools.com
Installation
npm install botws-fca
# or
yarn add botws-fcaQuick start
Callback style (ws3-fca drop-in)
const fca = require('botws-fca');
fca.login(
{
cookie: 'c_user=YOUR_UID; xs=YOUR_XS; ...', // or appState array
apiKey: 'YOUR_KHOTOOLS_API_KEY',
apiUrl: 'https://api.khotools.com', // default, can omit
},
(err, api) => {
if (err) return console.error(err);
api.listen((err, event) => {
if (err) return console.error(err);
if (event.type === 'message') {
api.sendMessage('Hello from botws-fca!', event.threadID);
}
});
}
);Promise / async-await style
const fca = require('botws-fca');
async function main() {
const api = await fca.login({
cookie: 'c_user=...; xs=...;',
apiKey: 'YOUR_KHOTOOLS_API_KEY',
});
api.listen(async (err, event) => {
if (event.type === 'message') {
await api.sendMessage('pong', event.threadID);
}
});
}
main().catch(console.error);Using appState (fbstate) instead of a raw cookie string
const appState = require('./fbstate.json'); // array of { key, value, domain, ... }
const api = await fca.login({ appState, apiKey: 'YOUR_KEY' });Configuration reference
| Field | Aliases | Required | Description |
|-------|---------|----------|-------------|
| cookie | appState, fbstate, state | yes | Facebook session cookie string or fbstate array |
| apiKey | api_key, key | yes | Khotools API key |
| apiUrl | api_url, url | no | Khotools API base URL (default: https://api.khotools.com) |
| wsUrl | ws_url, wsURL | no | Override the WebSocket URL (auto-derived from apiUrl if omitted) |
| botName | BOTNAME, name | no | Display name for the session |
| fca | | no | FCA version: "fcaPrime" (default) or "fca2" |
| reconnectMinutes | | no | Scheduled reconnect interval in minutes (default: 60) |
| reconnectMs | reconnectIntervalMs | no | Reconnect interval in milliseconds (overrides reconnectMinutes) |
| facebookAccount | account | no | { email, password } for auto-login fallback |
API reference
Every method mirrors ws3-fca exactly. All methods accept an optional callback (err, result) => void as the last argument. When the callback is omitted the method returns a Promise.
Messaging
// Send a text message
api.sendMessage('Hello!', threadID);
// Send with attachment (stream or Buffer)
const fs = require('fs');
api.sendMessage({ body: 'Here is a photo', attachment: fs.createReadStream('./photo.jpg') }, threadID);
// Reply to a message
api.sendMessage('Got it!', threadID, callback, messageID);
// or (third-arg reply shorthand used by some bots)
api.sendMessage('Got it!', threadID, messageID);
// Aliases expected by GoatBot / similar frameworks
api.sendMessageMqtt(msg, threadID);
api.sendMessageMqttv2(msg, threadID);
// Remove a sent message
api.unsendMessage(messageID);
// React to a message
api.setMessageReaction('😍', messageID);
// Remove a reaction
api.setMessageReaction('', messageID);Thread & user info
const threadInfo = await api.getThreadInfo(threadID);
// threadInfo.threadName, .participantIDs, .adminIDs, .emoji, .color …
const threads = await api.getThreadList(10, null, ['INBOX']);
const users = await api.getUserInfo(['123456789', '987654321']);
// users['123456789'].name, .profileUrl, .thumbSrc …
const message = await api.getMessage(threadID, messageID);Group management
// Add / remove users
api.addUserToGroup(userID, threadID);
api.addUserToGroup([uid1, uid2], threadID); // multiple at once
api.removeUserFromGroup(userID, threadID);
// Admin
api.changeAdminStatus(threadID, userID, true); // promote
api.changeAdminStatus(threadID, userID, false); // demote
// Group settings
api.setTitle('New group name', threadID);
api.gcname('New group name', threadID); // alias for setTitle
api.changeGroupImage(fs.createReadStream('./icon.jpg'), threadID);
api.changeThreadColor('#0084ff', threadID);
api.changeThreadEmoji('🎉', threadID);
api.setNickname('Nickname', threadID, participantID);
// Group call
api.callGroup(threadID);
api.callGroup(threadID, callback);Contact & presence
api.shareContact('Check out this person', userID, threadID);
api.sendTypingIndicator(threadID);
api.markAsRead(threadID);
api.markAsReadAll();
api.markAsDelivered(threadID, messageID);
api.markAsSeen(Date.now());Misc
const photoUrl = await api.resolvePhotoUrl(photoID);
api.emojiMqtt('❤️', 5, threadID); // animated emoji burst
const myUID = api.getCurrentUserID();
api.logout();Listening for events
// Identical to ws3-fca
const stopListening = api.listen((err, event) => {
if (err) return console.error(err);
console.log(event.type, event);
});
// listenMqtt is an alias
api.listenMqtt((err, event) => { ... });Common event types (same as ws3-fca):
| type | Description |
|------|-------------|
| message | Incoming text / attachment message |
| message_reply | Reply to an existing message |
| message_reaction | Reaction added/removed |
| message_unsend | Message unsent |
| event | Group join/leave/name change etc. |
| read_receipt | Read receipt from participant |
| typing | Typing indicator |
Migrating from ws3-fca
If your bot currently does:
const login = require('@tas33n/ws3-fca');
login({ appState }, (err, api) => { ... });Change it to:
const { login } = require('botws-fca');
login({ appState, apiKey: 'YOUR_KHOTOOLS_KEY' }, (err, api) => { ... });That's it — every api.* call in your bot works unchanged.
Goat-Bot / similar framework integration
This package is designed to work as a direct replacement for the FCA dependency used in Goat-Bot, NashBot, and similar frameworks. In your bot's main entry point:
// Replace:
const { login } = require('@tas33n/ws3-fca');
// With:
const { login } = require('botws-fca');Pass your apiKey and apiUrl in the credentials object (or merge them into your existing config) and everything else stays the same.
Getting a Khotools API key
- Go to https://khotools.com
- Register or log in
- Navigate to the API-Key tab
- Create a new key and copy it
- Pass it as
apiKeyin thelogin()call
License
ISC
