surya-sahil-fca 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 +175 -0
- package/DOCS.md +2636 -0
- package/LICENSE-MIT +21 -0
- package/README.md +107 -0
- package/func/checkUpdate.js +222 -0
- package/func/logger.js +48 -0
- package/index.d.ts +746 -0
- package/index.js +8 -0
- package/module/config.js +34 -0
- package/module/login.js +126 -0
- package/module/loginHelper.js +747 -0
- package/module/options.js +45 -0
- package/package.json +82 -0
- package/src/api/messaging/changeGroupImage.js +90 -0
- package/src/api/messaging/changeNickname.js +70 -0
- package/src/api/messaging/changeThreadName.js +123 -0
- package/src/api/messaging/createCommentPost.js +207 -0
- package/src/api/messaging/sendMessage.js +272 -0
- package/src/api/messaging/sendTypingIndicator.js +67 -0
- package/src/api/messaging/setMessageReaction.js +76 -0
- package/src/api/messaging/setTitle.js +119 -0
- package/src/api/messaging/stickers.js +257 -0
- package/src/core/sendReqMqtt.js +96 -0
- package/src/database/models/index.js +49 -0
- package/src/database/models/thread.js +31 -0
- package/src/database/models/user.js +32 -0
- package/src/database/threadData.js +98 -0
- package/src/database/userData.js +89 -0
- package/src/utils/client.js +320 -0
- package/src/utils/constants.js +23 -0
- package/src/utils/format.js +1115 -0
- package/src/utils/headers.js +115 -0
- package/src/utils/request.js +305 -0
package/DOCS.md
ADDED
|
@@ -0,0 +1,2636 @@
|
|
|
1
|
+
# FCA-Unofficial - Complete API Documentation
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
**surya-sahil-fca** is an unofficial Node.js library for interacting with Facebook Messenger by emulating browser behavior. This library allows you to create chat bots and automate tasks on Facebook Messenger.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install surya-sahil-fca@latest
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. LOGIN
|
|
16
|
+
|
|
17
|
+
### 1.1. Login with Email & Password
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
const login = require("surya-sahil-fca");
|
|
21
|
+
|
|
22
|
+
const credentials = {
|
|
23
|
+
email: "your_email@example.com",
|
|
24
|
+
password: "your_password"
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
login(credentials, (err, api) => {
|
|
28
|
+
if (err) {
|
|
29
|
+
console.error("Login error:", err);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log("Login successful!");
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 1.2. Login with 2FA (Two-Factor Authentication)
|
|
37
|
+
|
|
38
|
+
When your account has 2FA enabled, you need to provide the 2FA code:
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
const login = require("surya-sahil-fca");
|
|
42
|
+
const readline = require("readline");
|
|
43
|
+
|
|
44
|
+
const rl = readline.createInterface({
|
|
45
|
+
input: process.stdin,
|
|
46
|
+
output: process.stdout
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const credentials = {
|
|
50
|
+
email: "your_email@example.com",
|
|
51
|
+
password: "your_password"
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
login(credentials, (err, api) => {
|
|
55
|
+
if (err) {
|
|
56
|
+
// If 2FA is required
|
|
57
|
+
if (err.error === 'login-approval') {
|
|
58
|
+
console.log("2FA code required!");
|
|
59
|
+
|
|
60
|
+
rl.question("Enter 2FA code: ", (code) => {
|
|
61
|
+
err.continue(code);
|
|
62
|
+
rl.close();
|
|
63
|
+
});
|
|
64
|
+
} else {
|
|
65
|
+
console.error("Login error:", err);
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log("Login successful!");
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 1.3. Login with AppState (Recommended)
|
|
75
|
+
|
|
76
|
+
AppState is saved cookies and session data. Login with AppState helps avoid entering password each time and reduces checkpoint risk.
|
|
77
|
+
|
|
78
|
+
#### Get and Save AppState:
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
const fs = require("fs");
|
|
82
|
+
const login = require("surya-sahil-fca");
|
|
83
|
+
|
|
84
|
+
const credentials = {
|
|
85
|
+
email: "your_email@example.com",
|
|
86
|
+
password: "your_password"
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
login(credentials, (err, api) => {
|
|
90
|
+
if (err) {
|
|
91
|
+
console.error("Login error:", err);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Save AppState to file
|
|
96
|
+
try {
|
|
97
|
+
const appState = api.getAppState();
|
|
98
|
+
fs.writeFileSync("appstate.json", JSON.stringify(appState, null, 2));
|
|
99
|
+
console.log("✅ AppState saved!");
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error("Error saving AppState:", error);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### Use Saved AppState:
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
const fs = require("fs");
|
|
110
|
+
const login = require("surya-sahil-fca");
|
|
111
|
+
|
|
112
|
+
const credentials = {
|
|
113
|
+
appState: JSON.parse(fs.readFileSync("appstate.json", "utf8"))
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
login(credentials, (err, api) => {
|
|
117
|
+
if (err) {
|
|
118
|
+
console.error("Login error:", err);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log("Login successful with AppState!");
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Note:** You can use [c3c-fbstate](https://github.com/c3cbot/c3c-fbstate) tool to get AppState from browser.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 2. CONFIGURATION (Options)
|
|
131
|
+
|
|
132
|
+
After login, you can configure API options:
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
api.setOptions({
|
|
136
|
+
// Listen to events (add/remove members, change group name, etc.)
|
|
137
|
+
listenEvents: true,
|
|
138
|
+
|
|
139
|
+
// Listen to your own messages
|
|
140
|
+
selfListen: false,
|
|
141
|
+
|
|
142
|
+
// Auto mark messages as read
|
|
143
|
+
autoMarkRead: false,
|
|
144
|
+
|
|
145
|
+
// Auto mark as delivered
|
|
146
|
+
autoMarkDelivery: false,
|
|
147
|
+
|
|
148
|
+
// Online status (true/false)
|
|
149
|
+
online: true,
|
|
150
|
+
|
|
151
|
+
// Log level (silent/error/warn/info/verbose)
|
|
152
|
+
logLevel: "info",
|
|
153
|
+
|
|
154
|
+
// Custom user agent
|
|
155
|
+
userAgent: "Mozilla/5.0..."
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 3. DETAILED API METHODS
|
|
162
|
+
|
|
163
|
+
### 3.1. sendMessage - Send Message
|
|
164
|
+
|
|
165
|
+
Send message to user or group chat.
|
|
166
|
+
|
|
167
|
+
#### Syntax:
|
|
168
|
+
```javascript
|
|
169
|
+
api.sendMessage(message, threadID, [messageID], [callback])
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### Parameters:
|
|
173
|
+
- `message`: Message content (string or object)
|
|
174
|
+
- `threadID`: Conversation ID (user ID or group ID)
|
|
175
|
+
- `messageID`: (Optional) Message ID to reply to
|
|
176
|
+
- `callback`: (Optional) Callback function `(err, messageInfo)`
|
|
177
|
+
|
|
178
|
+
#### Basic Example:
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
api.sendMessage("Hello!", "100012345678901", (err, messageInfo) => {
|
|
182
|
+
if (err) {
|
|
183
|
+
console.error("Send message error:", err);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
console.log("Message sent, ID:", messageInfo.messageID);
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### Send Messages with Various Content Types:
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
// 1. Simple text message
|
|
194
|
+
api.sendMessage("Hello World", threadID);
|
|
195
|
+
|
|
196
|
+
// 2. Send sticker
|
|
197
|
+
api.sendMessage({
|
|
198
|
+
sticker: "767334476655547" // Sticker ID
|
|
199
|
+
}, threadID);
|
|
200
|
+
|
|
201
|
+
// 3. Send emoji with size
|
|
202
|
+
api.sendMessage({
|
|
203
|
+
body: "Awesome!",
|
|
204
|
+
emoji: "👍",
|
|
205
|
+
emojiSize: "large" // small, medium, large
|
|
206
|
+
}, threadID);
|
|
207
|
+
|
|
208
|
+
// 4. Send file/image
|
|
209
|
+
const fs = require("fs");
|
|
210
|
+
api.sendMessage({
|
|
211
|
+
body: "Here is an image",
|
|
212
|
+
attachment: fs.createReadStream("./image.jpg")
|
|
213
|
+
}, threadID);
|
|
214
|
+
|
|
215
|
+
// 5. Send multiple files
|
|
216
|
+
api.sendMessage({
|
|
217
|
+
body: "Multiple attachments",
|
|
218
|
+
attachment: [
|
|
219
|
+
fs.createReadStream("./image1.jpg"),
|
|
220
|
+
fs.createReadStream("./image2.jpg"),
|
|
221
|
+
fs.createReadStream("./document.pdf")
|
|
222
|
+
]
|
|
223
|
+
}, threadID);
|
|
224
|
+
|
|
225
|
+
// 6. Send URL
|
|
226
|
+
api.sendMessage({
|
|
227
|
+
body: "Check this link",
|
|
228
|
+
url: "https://example.com"
|
|
229
|
+
}, threadID);
|
|
230
|
+
|
|
231
|
+
// 7. Reply to message
|
|
232
|
+
api.sendMessage({
|
|
233
|
+
body: "This is a reply"
|
|
234
|
+
}, threadID, messageID);
|
|
235
|
+
|
|
236
|
+
// 8. Mention users
|
|
237
|
+
api.sendMessage({
|
|
238
|
+
body: "Hello @User1 and @User2!",
|
|
239
|
+
mentions: [
|
|
240
|
+
{
|
|
241
|
+
tag: "@User1",
|
|
242
|
+
id: "100012345678901",
|
|
243
|
+
fromIndex: 6 // Starting position of @User1
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
tag: "@User2",
|
|
247
|
+
id: "100012345678902",
|
|
248
|
+
fromIndex: 17
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
}, threadID);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### 3.2. listenMqtt - Listen for Messages
|
|
257
|
+
|
|
258
|
+
Listen for messages and events from Facebook Messenger (using MQTT).
|
|
259
|
+
|
|
260
|
+
#### Syntax:
|
|
261
|
+
```javascript
|
|
262
|
+
const stopListening = api.listenMqtt(callback);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Parameters:
|
|
266
|
+
- `callback`: Function `(err, event)` called when new message/event arrives
|
|
267
|
+
|
|
268
|
+
#### Example:
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
const stopListening = api.listenMqtt((err, event) => {
|
|
272
|
+
if (err) {
|
|
273
|
+
console.error("Listen error:", err);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Handle events
|
|
278
|
+
switch (event.type) {
|
|
279
|
+
case "message":
|
|
280
|
+
console.log("New message:", event.body);
|
|
281
|
+
console.log("From user:", event.senderID);
|
|
282
|
+
console.log("In conversation:", event.threadID);
|
|
283
|
+
|
|
284
|
+
// Reply to message
|
|
285
|
+
if (event.body === "Hi") {
|
|
286
|
+
api.sendMessage("Hello!", event.threadID);
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
|
|
290
|
+
case "event":
|
|
291
|
+
console.log("Event:", event.logMessageType);
|
|
292
|
+
// log_message_type can be:
|
|
293
|
+
// - log:subscribe (member added)
|
|
294
|
+
// - log:unsubscribe (member removed)
|
|
295
|
+
// - log:thread-name (group name changed)
|
|
296
|
+
// - log:thread-icon (group icon changed)
|
|
297
|
+
// - log:thread-color (chat color changed)
|
|
298
|
+
break;
|
|
299
|
+
|
|
300
|
+
case "typ":
|
|
301
|
+
console.log(event.from, "is typing...");
|
|
302
|
+
break;
|
|
303
|
+
|
|
304
|
+
case "read_receipt":
|
|
305
|
+
console.log("Message read by:", event.reader);
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Stop listening
|
|
311
|
+
// stopListening();
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
#### Event Object Details:
|
|
315
|
+
|
|
316
|
+
```javascript
|
|
317
|
+
// Event type: "message"
|
|
318
|
+
{
|
|
319
|
+
type: "message",
|
|
320
|
+
threadID: "1234567890",
|
|
321
|
+
messageID: "mid.xxx",
|
|
322
|
+
senderID: "100012345678901",
|
|
323
|
+
body: "Message content",
|
|
324
|
+
args: ["Message", "content"], // Array of words from body (split by whitespace)
|
|
325
|
+
attachments: [], // Array of attachments
|
|
326
|
+
mentions: {}, // Object of mentions
|
|
327
|
+
timestamp: 1234567890000,
|
|
328
|
+
isGroup: false, // true if group chat
|
|
329
|
+
isUnread: false, // Whether message is unread
|
|
330
|
+
participantIDs: ["100012345678901"] // Array of participant IDs
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Event type: "event"
|
|
334
|
+
{
|
|
335
|
+
type: "event",
|
|
336
|
+
threadID: "1234567890",
|
|
337
|
+
logMessageType: "log:subscribe",
|
|
338
|
+
logMessageData: {...},
|
|
339
|
+
author: "100012345678901"
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Event type: "typ" (typing)
|
|
343
|
+
{
|
|
344
|
+
type: "typ",
|
|
345
|
+
threadID: "1234567890",
|
|
346
|
+
from: "100012345678901",
|
|
347
|
+
isTyping: true
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Event type: "read_receipt" (read)
|
|
351
|
+
{
|
|
352
|
+
type: "read_receipt",
|
|
353
|
+
threadID: "1234567890",
|
|
354
|
+
reader: "100012345678901",
|
|
355
|
+
time: 1234567890000
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
### 3.3. Middleware System - Filter and Process Events
|
|
362
|
+
|
|
363
|
+
The middleware system allows you to intercept, filter, and modify events before they are emitted to your callback. This is useful for logging, rate limiting, message filtering, auto-replies, and more.
|
|
364
|
+
|
|
365
|
+
#### Syntax:
|
|
366
|
+
```javascript
|
|
367
|
+
// Add middleware
|
|
368
|
+
const removeMiddleware = api.useMiddleware(middlewareFunction);
|
|
369
|
+
const removeMiddleware = api.useMiddleware("middlewareName", middlewareFunction);
|
|
370
|
+
|
|
371
|
+
// Remove middleware
|
|
372
|
+
api.removeMiddleware(identifier); // identifier can be name (string) or function
|
|
373
|
+
|
|
374
|
+
// Clear all middleware
|
|
375
|
+
api.clearMiddleware();
|
|
376
|
+
|
|
377
|
+
// List middleware
|
|
378
|
+
const names = api.listMiddleware();
|
|
379
|
+
|
|
380
|
+
// Enable/disable middleware
|
|
381
|
+
api.setMiddlewareEnabled("middlewareName", true); // enable
|
|
382
|
+
api.setMiddlewareEnabled("middlewareName", false); // disable
|
|
383
|
+
|
|
384
|
+
// Get middleware count
|
|
385
|
+
const count = api.middlewareCount;
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### Middleware Function Signature:
|
|
389
|
+
```javascript
|
|
390
|
+
function middleware(event, next) {
|
|
391
|
+
// event: The event object (can be modified)
|
|
392
|
+
// next: Function to continue to next middleware
|
|
393
|
+
// - next() - continue to next middleware
|
|
394
|
+
// - next(false) or next(null) - stop processing, don't emit event
|
|
395
|
+
// - next(error) - emit error instead
|
|
396
|
+
|
|
397
|
+
// Your logic here
|
|
398
|
+
|
|
399
|
+
next(); // Continue to next middleware
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
#### Examples:
|
|
404
|
+
|
|
405
|
+
**1. Message Filtering - Block messages from specific users:**
|
|
406
|
+
```javascript
|
|
407
|
+
api.useMiddleware("blockUsers", (event, next) => {
|
|
408
|
+
if (event.type === "message") {
|
|
409
|
+
const blockedUsers = ["100012345678901", "100012345678902"];
|
|
410
|
+
if (blockedUsers.includes(event.senderID)) {
|
|
411
|
+
// Block this message
|
|
412
|
+
return next(false);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
next(); // Continue processing
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**2. Logging Middleware:**
|
|
420
|
+
```javascript
|
|
421
|
+
api.useMiddleware("logger", (event, next) => {
|
|
422
|
+
if (event.type === "message") {
|
|
423
|
+
console.log(`[${new Date().toISOString()}] Message from ${event.senderID}: ${event.body}`);
|
|
424
|
+
}
|
|
425
|
+
next(); // Continue to next middleware
|
|
426
|
+
});
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**3. Auto-Reply Middleware:**
|
|
430
|
+
```javascript
|
|
431
|
+
api.useMiddleware("autoReply", (event, next) => {
|
|
432
|
+
if (event.type === "message" && event.body.toLowerCase() === "hello") {
|
|
433
|
+
api.sendMessage("Hi there! How can I help you?", event.threadID);
|
|
434
|
+
}
|
|
435
|
+
next(); // Continue processing
|
|
436
|
+
});
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
**4. Rate Limiting Middleware:**
|
|
440
|
+
```javascript
|
|
441
|
+
const messageCounts = {};
|
|
442
|
+
const RATE_LIMIT = 10; // messages per minute
|
|
443
|
+
const RATE_WINDOW = 60000; // 1 minute
|
|
444
|
+
|
|
445
|
+
api.useMiddleware("rateLimit", (event, next) => {
|
|
446
|
+
if (event.type === "message") {
|
|
447
|
+
const now = Date.now();
|
|
448
|
+
const senderID = event.senderID;
|
|
449
|
+
|
|
450
|
+
// Clean old entries
|
|
451
|
+
if (messageCounts[senderID] && messageCounts[senderID].timestamp < now - RATE_WINDOW) {
|
|
452
|
+
delete messageCounts[senderID];
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Initialize or increment
|
|
456
|
+
if (!messageCounts[senderID]) {
|
|
457
|
+
messageCounts[senderID] = { count: 0, timestamp: now };
|
|
458
|
+
}
|
|
459
|
+
messageCounts[senderID].count++;
|
|
460
|
+
|
|
461
|
+
// Check rate limit
|
|
462
|
+
if (messageCounts[senderID].count > RATE_LIMIT) {
|
|
463
|
+
console.log(`Rate limit exceeded for user ${senderID}`);
|
|
464
|
+
return next(false); // Block message
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
next();
|
|
468
|
+
});
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**5. Message Transformation:**
|
|
472
|
+
```javascript
|
|
473
|
+
api.useMiddleware("transform", (event, next) => {
|
|
474
|
+
if (event.type === "message") {
|
|
475
|
+
// Add custom property
|
|
476
|
+
event.customProperty = "customValue";
|
|
477
|
+
|
|
478
|
+
// Transform message body
|
|
479
|
+
if (event.body) {
|
|
480
|
+
event.body = event.body.toUpperCase();
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
next();
|
|
484
|
+
});
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
**6. Async Middleware (Promise-based):**
|
|
488
|
+
```javascript
|
|
489
|
+
api.useMiddleware("asyncMiddleware", async (event, next) => {
|
|
490
|
+
if (event.type === "message") {
|
|
491
|
+
// Do async operation
|
|
492
|
+
const userInfo = await api.getUserInfo(event.senderID);
|
|
493
|
+
event.senderName = userInfo[event.senderID].name;
|
|
494
|
+
}
|
|
495
|
+
next(); // Continue
|
|
496
|
+
});
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
**7. Conditional Middleware:**
|
|
500
|
+
```javascript
|
|
501
|
+
// Only process messages in group chats
|
|
502
|
+
api.useMiddleware("groupOnly", (event, next) => {
|
|
503
|
+
if (event.type === "message" && !event.isGroup) {
|
|
504
|
+
return next(false); // Skip non-group messages
|
|
505
|
+
}
|
|
506
|
+
next();
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
// Only process messages containing specific keywords
|
|
510
|
+
api.useMiddleware("keywordFilter", (event, next) => {
|
|
511
|
+
if (event.type === "message") {
|
|
512
|
+
const keywords = ["help", "support", "info"];
|
|
513
|
+
const hasKeyword = keywords.some(keyword =>
|
|
514
|
+
event.body.toLowerCase().includes(keyword)
|
|
515
|
+
);
|
|
516
|
+
if (!hasKeyword) {
|
|
517
|
+
return next(false); // Skip messages without keywords
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
next();
|
|
521
|
+
});
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
**8. Remove Middleware:**
|
|
525
|
+
```javascript
|
|
526
|
+
// Remove by name
|
|
527
|
+
api.removeMiddleware("logger");
|
|
528
|
+
|
|
529
|
+
// Remove by function reference
|
|
530
|
+
const myMiddleware = (event, next) => { /* ... */ };
|
|
531
|
+
api.useMiddleware("myMiddleware", myMiddleware);
|
|
532
|
+
// Later...
|
|
533
|
+
api.removeMiddleware(myMiddleware);
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**9. Complete Example - Bot with Multiple Middleware:**
|
|
537
|
+
```javascript
|
|
538
|
+
const login = require("surya-sahil-fca");
|
|
539
|
+
|
|
540
|
+
login({ appState: [] }, (err, api) => {
|
|
541
|
+
if (err) return console.error(err);
|
|
542
|
+
|
|
543
|
+
// 1. Logging middleware
|
|
544
|
+
api.useMiddleware("logger", (event, next) => {
|
|
545
|
+
if (event.type === "message") {
|
|
546
|
+
console.log(`Message: ${event.body}`);
|
|
547
|
+
}
|
|
548
|
+
next();
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// 2. Block spam users
|
|
552
|
+
const spamUsers = ["100012345678901"];
|
|
553
|
+
api.useMiddleware("spamFilter", (event, next) => {
|
|
554
|
+
if (event.type === "message" && spamUsers.includes(event.senderID)) {
|
|
555
|
+
return next(false);
|
|
556
|
+
}
|
|
557
|
+
next();
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
// 3. Auto-reply to greetings
|
|
561
|
+
api.useMiddleware("autoReply", (event, next) => {
|
|
562
|
+
if (event.type === "message") {
|
|
563
|
+
const greetings = ["hi", "hello", "hey"];
|
|
564
|
+
if (greetings.includes(event.body.toLowerCase())) {
|
|
565
|
+
api.sendMessage("Hello! How can I help?", event.threadID);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
next();
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
// 4. Listen for messages (middleware will process them first)
|
|
572
|
+
api.listenMqtt((err, event) => {
|
|
573
|
+
if (err) return console.error(err);
|
|
574
|
+
|
|
575
|
+
// This callback receives events AFTER middleware processing
|
|
576
|
+
if (event.type === "message") {
|
|
577
|
+
console.log("Received message:", event.body);
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
});
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
#### Middleware Execution Order:
|
|
584
|
+
Middleware functions are executed in the order they are added. If a middleware calls `next(false)` or `next(null)`, the event will be blocked and not emitted to your callback.
|
|
585
|
+
|
|
586
|
+
#### Notes:
|
|
587
|
+
- Middleware only processes events, not errors (errors bypass middleware)
|
|
588
|
+
- You can modify the event object in middleware (it will be passed to the next middleware and callback)
|
|
589
|
+
- Middleware can be async (return a Promise)
|
|
590
|
+
- Middleware can be enabled/disabled without removing them
|
|
591
|
+
- The middleware system is persistent across reconnections
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
### 3.4. getUserInfo - Get User Information
|
|
596
|
+
|
|
597
|
+
Get detailed information about one or more users.
|
|
598
|
+
|
|
599
|
+
#### Syntax:
|
|
600
|
+
```javascript
|
|
601
|
+
api.getUserInfo(userID, callback);
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
#### Example:
|
|
605
|
+
|
|
606
|
+
```javascript
|
|
607
|
+
// Get info for 1 user
|
|
608
|
+
api.getUserInfo("100012345678901", (err, userInfo) => {
|
|
609
|
+
if (err) {
|
|
610
|
+
console.error(err);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
console.log(userInfo);
|
|
615
|
+
// {
|
|
616
|
+
// "100012345678901": {
|
|
617
|
+
// name: "John Doe",
|
|
618
|
+
// firstName: "John",
|
|
619
|
+
// vanity: "john.doe",
|
|
620
|
+
// thumbSrc: "avatar_url",
|
|
621
|
+
// profileUrl: "https://facebook.com/john.doe",
|
|
622
|
+
// gender: "MALE", // MALE/FEMALE
|
|
623
|
+
// type: "user",
|
|
624
|
+
// isFriend: true,
|
|
625
|
+
// isBirthday: false
|
|
626
|
+
// }
|
|
627
|
+
// }
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
// Get info for multiple users
|
|
631
|
+
api.getUserInfo(["100012345678901", "100012345678902"], (err, userInfo) => {
|
|
632
|
+
if (err) return console.error(err);
|
|
633
|
+
|
|
634
|
+
for (let id in userInfo) {
|
|
635
|
+
console.log(userInfo[id].name);
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
### 3.4. Message Scheduler - Schedule Messages
|
|
643
|
+
|
|
644
|
+
Schedule messages to be sent at a specific time in the future. Useful for reminders, scheduled announcements, and automated messages.
|
|
645
|
+
|
|
646
|
+
#### Syntax:
|
|
647
|
+
```javascript
|
|
648
|
+
// Schedule a message
|
|
649
|
+
const id = api.scheduler.scheduleMessage(message, threadID, when, options);
|
|
650
|
+
|
|
651
|
+
// Cancel a scheduled message
|
|
652
|
+
api.scheduler.cancelScheduledMessage(id);
|
|
653
|
+
|
|
654
|
+
// Get scheduled message info
|
|
655
|
+
const scheduled = api.scheduler.getScheduledMessage(id);
|
|
656
|
+
|
|
657
|
+
// List all scheduled messages
|
|
658
|
+
const list = api.scheduler.listScheduledMessages();
|
|
659
|
+
|
|
660
|
+
// Cancel all scheduled messages
|
|
661
|
+
const count = api.scheduler.cancelAllScheduledMessages();
|
|
662
|
+
|
|
663
|
+
// Get count of scheduled messages
|
|
664
|
+
const count = api.scheduler.getScheduledCount();
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
#### Parameters:
|
|
668
|
+
- `message`: Message content (string or MessageObject)
|
|
669
|
+
- `threadID`: Target thread ID(s) (string or array)
|
|
670
|
+
- `when`: When to send - can be:
|
|
671
|
+
- `Date` object
|
|
672
|
+
- `number` (Unix timestamp in milliseconds)
|
|
673
|
+
- `string` (ISO date string)
|
|
674
|
+
- `options`: Optional object with:
|
|
675
|
+
- `replyMessageID`: Message ID to reply to
|
|
676
|
+
- `isGroup`: Whether it's a group chat
|
|
677
|
+
- `callback`: Callback function when message is sent
|
|
678
|
+
|
|
679
|
+
#### Examples:
|
|
680
|
+
|
|
681
|
+
**1. Schedule message for specific time:**
|
|
682
|
+
```javascript
|
|
683
|
+
// Schedule for 1 hour from now
|
|
684
|
+
const oneHourLater = Date.now() + (60 * 60 * 1000);
|
|
685
|
+
const id = api.scheduler.scheduleMessage(
|
|
686
|
+
"This is a scheduled message!",
|
|
687
|
+
"100012345678901",
|
|
688
|
+
oneHourLater
|
|
689
|
+
);
|
|
690
|
+
console.log(`Message scheduled with ID: ${id}`);
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
**2. Schedule using Date object:**
|
|
694
|
+
```javascript
|
|
695
|
+
// Schedule for tomorrow at 9:00 AM
|
|
696
|
+
const tomorrow = new Date();
|
|
697
|
+
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
698
|
+
tomorrow.setHours(9, 0, 0, 0);
|
|
699
|
+
|
|
700
|
+
const id = api.scheduler.scheduleMessage(
|
|
701
|
+
"Good morning! ☀️",
|
|
702
|
+
"100012345678901",
|
|
703
|
+
tomorrow
|
|
704
|
+
);
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
**3. Schedule using ISO string:**
|
|
708
|
+
```javascript
|
|
709
|
+
// Schedule for specific date/time
|
|
710
|
+
const id = api.scheduler.scheduleMessage(
|
|
711
|
+
"Meeting reminder!",
|
|
712
|
+
"100012345678901",
|
|
713
|
+
"2024-12-25T10:00:00Z"
|
|
714
|
+
);
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
**4. Schedule with options:**
|
|
718
|
+
```javascript
|
|
719
|
+
const id = api.scheduler.scheduleMessage(
|
|
720
|
+
"Reply to your message",
|
|
721
|
+
"100012345678901",
|
|
722
|
+
Date.now() + 30000, // 30 seconds from now
|
|
723
|
+
{
|
|
724
|
+
replyMessageID: "mid.xxx",
|
|
725
|
+
isGroup: false,
|
|
726
|
+
callback: (err) => {
|
|
727
|
+
if (err) {
|
|
728
|
+
console.error("Scheduled message failed:", err);
|
|
729
|
+
} else {
|
|
730
|
+
console.log("Scheduled message sent!");
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
);
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
**5. Cancel scheduled message:**
|
|
738
|
+
```javascript
|
|
739
|
+
const id = api.scheduler.scheduleMessage("Test", threadID, Date.now() + 60000);
|
|
740
|
+
|
|
741
|
+
// Cancel it
|
|
742
|
+
if (api.scheduler.cancelScheduledMessage(id)) {
|
|
743
|
+
console.log("Message cancelled");
|
|
744
|
+
} else {
|
|
745
|
+
console.log("Message not found or already sent");
|
|
746
|
+
}
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
**6. List all scheduled messages:**
|
|
750
|
+
```javascript
|
|
751
|
+
const scheduled = api.scheduler.listScheduledMessages();
|
|
752
|
+
|
|
753
|
+
scheduled.forEach(msg => {
|
|
754
|
+
const timeUntil = Math.round(msg.timeUntilSend / 1000 / 60); // minutes
|
|
755
|
+
console.log(`ID: ${msg.id}, Sends in ${timeUntil} minutes`);
|
|
756
|
+
});
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
**7. Get scheduled message info:**
|
|
760
|
+
```javascript
|
|
761
|
+
const scheduled = api.scheduler.getScheduledMessage(id);
|
|
762
|
+
if (scheduled) {
|
|
763
|
+
console.log("Message:", scheduled.message);
|
|
764
|
+
console.log("Scheduled for:", new Date(scheduled.timestamp));
|
|
765
|
+
console.log("Time until send:", scheduled.timeUntilSend, "ms");
|
|
766
|
+
}
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
**8. Complete example - Reminder bot:**
|
|
770
|
+
```javascript
|
|
771
|
+
const login = require("surya-sahil-fca");
|
|
772
|
+
|
|
773
|
+
login({ appState: [] }, (err, api) => {
|
|
774
|
+
if (err) return console.error(err);
|
|
775
|
+
|
|
776
|
+
api.listenMqtt((err, event) => {
|
|
777
|
+
if (err) return console.error(err);
|
|
778
|
+
|
|
779
|
+
if (event.type === "message" && event.body.startsWith("/remind")) {
|
|
780
|
+
const args = event.body.split(" ");
|
|
781
|
+
if (args.length < 3) {
|
|
782
|
+
api.sendMessage("Usage: /remind <minutes> <message>", event.threadID);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
const minutes = parseInt(args[1]);
|
|
787
|
+
const message = args.slice(2).join(" ");
|
|
788
|
+
const when = Date.now() + (minutes * 60 * 1000);
|
|
789
|
+
|
|
790
|
+
const id = api.scheduler.scheduleMessage(
|
|
791
|
+
message,
|
|
792
|
+
event.threadID,
|
|
793
|
+
when
|
|
794
|
+
);
|
|
795
|
+
|
|
796
|
+
api.sendMessage(
|
|
797
|
+
`Reminder scheduled! I'll remind you in ${minutes} minutes.`,
|
|
798
|
+
event.threadID
|
|
799
|
+
);
|
|
800
|
+
}
|
|
801
|
+
});
|
|
802
|
+
});
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
#### Notes:
|
|
806
|
+
- Scheduled messages are stored in memory and will be lost if the bot restarts
|
|
807
|
+
- Messages are sent automatically at the scheduled time
|
|
808
|
+
- You can cancel messages before they are sent
|
|
809
|
+
- The scheduler automatically cleans up expired messages
|
|
810
|
+
|
|
811
|
+
---
|
|
812
|
+
|
|
813
|
+
### 3.5. Auto-save AppState
|
|
814
|
+
|
|
815
|
+
Automatically save AppState to a file at regular intervals to prevent session loss.
|
|
816
|
+
|
|
817
|
+
#### Syntax:
|
|
818
|
+
```javascript
|
|
819
|
+
// Enable auto-save
|
|
820
|
+
const disable = api.enableAutoSaveAppState(options);
|
|
821
|
+
|
|
822
|
+
// Disable auto-save
|
|
823
|
+
disable();
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
#### Parameters:
|
|
827
|
+
- `options`: Optional object with:
|
|
828
|
+
- `filePath`: Path to save AppState file (default: "appstate.json")
|
|
829
|
+
- `interval`: Save interval in milliseconds (default: 10 minutes)
|
|
830
|
+
- `saveOnLogin`: Save immediately on login (default: true)
|
|
831
|
+
|
|
832
|
+
#### Examples:
|
|
833
|
+
|
|
834
|
+
**1. Basic auto-save:**
|
|
835
|
+
```javascript
|
|
836
|
+
const login = require("surya-sahil-fca");
|
|
837
|
+
|
|
838
|
+
login({ appState: [] }, (err, api) => {
|
|
839
|
+
if (err) return console.error(err);
|
|
840
|
+
|
|
841
|
+
// Enable auto-save (saves every 10 minutes by default)
|
|
842
|
+
api.enableAutoSaveAppState();
|
|
843
|
+
});
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
**2. Custom file path and interval:**
|
|
847
|
+
```javascript
|
|
848
|
+
// Save to custom location every 5 minutes
|
|
849
|
+
const disable = api.enableAutoSaveAppState({
|
|
850
|
+
filePath: "./data/appstate.json",
|
|
851
|
+
interval: 5 * 60 * 1000, // 5 minutes
|
|
852
|
+
saveOnLogin: true
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
// Later, disable it
|
|
856
|
+
// disable();
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
**3. Save only on login:**
|
|
860
|
+
```javascript
|
|
861
|
+
// Save only once on login, not periodically
|
|
862
|
+
const disable = api.enableAutoSaveAppState({
|
|
863
|
+
interval: Infinity, // Never save periodically
|
|
864
|
+
saveOnLogin: true
|
|
865
|
+
});
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
**4. Complete example:**
|
|
869
|
+
```javascript
|
|
870
|
+
const fs = require("fs");
|
|
871
|
+
const login = require("surya-sahil-fca");
|
|
872
|
+
|
|
873
|
+
// Try to load existing AppState
|
|
874
|
+
let appState = [];
|
|
875
|
+
try {
|
|
876
|
+
appState = JSON.parse(fs.readFileSync("appstate.json", "utf8"));
|
|
877
|
+
} catch (e) {
|
|
878
|
+
console.log("No existing AppState found");
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
login({ appState }, (err, api) => {
|
|
882
|
+
if (err) return console.error(err);
|
|
883
|
+
|
|
884
|
+
// Enable auto-save
|
|
885
|
+
api.enableAutoSaveAppState({
|
|
886
|
+
filePath: "appstate.json",
|
|
887
|
+
interval: 10 * 60 * 1000, // 10 minutes
|
|
888
|
+
saveOnLogin: true
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
console.log("Bot started with auto-save enabled!");
|
|
892
|
+
});
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
#### Notes:
|
|
896
|
+
- AppState is saved automatically at the specified interval
|
|
897
|
+
- Saves immediately on login if `saveOnLogin` is true
|
|
898
|
+
- The save function checks if AppState is valid before saving
|
|
899
|
+
- Multiple auto-save instances can be enabled with different settings
|
|
900
|
+
|
|
901
|
+
---
|
|
902
|
+
|
|
903
|
+
### 3.6. getThreadInfo - Get Thread Information
|
|
904
|
+
|
|
905
|
+
Get information about conversation/group chat.
|
|
906
|
+
|
|
907
|
+
#### Syntax:
|
|
908
|
+
```javascript
|
|
909
|
+
api.getThreadInfo(threadID, callback);
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
#### Example:
|
|
913
|
+
|
|
914
|
+
```javascript
|
|
915
|
+
api.getThreadInfo("1234567890", (err, threadInfo) => {
|
|
916
|
+
if (err) {
|
|
917
|
+
console.error(err);
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
console.log("Group name:", threadInfo.threadName);
|
|
922
|
+
console.log("Member count:", threadInfo.participantIDs.length);
|
|
923
|
+
console.log("Members list:", threadInfo.participantIDs);
|
|
924
|
+
console.log("Admins:", threadInfo.adminIDs);
|
|
925
|
+
console.log("Nicknames:", threadInfo.nicknames);
|
|
926
|
+
console.log("Chat color:", threadInfo.color);
|
|
927
|
+
console.log("Emoji:", threadInfo.emoji);
|
|
928
|
+
});
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
---
|
|
932
|
+
|
|
933
|
+
### 3.5. changeThreadColor - Change Chat Color
|
|
934
|
+
|
|
935
|
+
Change the color of conversation.
|
|
936
|
+
|
|
937
|
+
#### Syntax:
|
|
938
|
+
```javascript
|
|
939
|
+
api.changeThreadColor(color, threadID, callback);
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
#### Example:
|
|
943
|
+
|
|
944
|
+
```javascript
|
|
945
|
+
// Color can be:
|
|
946
|
+
// "#0084ff" (Messenger Blue)
|
|
947
|
+
// "#44bec7" (Teal Blue)
|
|
948
|
+
// "#ffc300" (Yellow)
|
|
949
|
+
// "#fa3c4c" (Red)
|
|
950
|
+
// "#d696bb" (Pink)
|
|
951
|
+
// "#6699cc" (Sky Blue)
|
|
952
|
+
// "#13cf13" (Green)
|
|
953
|
+
// "#ff7e29" (Orange)
|
|
954
|
+
// "#e68585" (Light Red)
|
|
955
|
+
// "#7646ff" (Purple)
|
|
956
|
+
// "#20cef5" (Cyan)
|
|
957
|
+
// or any hex color code
|
|
958
|
+
|
|
959
|
+
api.changeThreadColor("#ffc300", "1234567890", (err) => {
|
|
960
|
+
if (err) {
|
|
961
|
+
console.error("Change color error:", err);
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
console.log("Chat color changed successfully!");
|
|
965
|
+
});
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
---
|
|
969
|
+
|
|
970
|
+
### 3.6. changeThreadEmoji - Change Group Emoji
|
|
971
|
+
|
|
972
|
+
Change the default emoji of conversation.
|
|
973
|
+
|
|
974
|
+
#### Syntax:
|
|
975
|
+
```javascript
|
|
976
|
+
api.changeThreadEmoji(emoji, threadID, callback);
|
|
977
|
+
```
|
|
978
|
+
|
|
979
|
+
#### Example:
|
|
980
|
+
|
|
981
|
+
```javascript
|
|
982
|
+
api.changeThreadEmoji("👍", "1234567890", (err) => {
|
|
983
|
+
if (err) {
|
|
984
|
+
console.error("Change emoji error:", err);
|
|
985
|
+
return;
|
|
986
|
+
}
|
|
987
|
+
console.log("Emoji changed successfully!");
|
|
988
|
+
});
|
|
989
|
+
```
|
|
990
|
+
|
|
991
|
+
---
|
|
992
|
+
|
|
993
|
+
### 3.7. setTitle - Change Group Name
|
|
994
|
+
|
|
995
|
+
Change the name of group chat.
|
|
996
|
+
|
|
997
|
+
#### Syntax:
|
|
998
|
+
```javascript
|
|
999
|
+
api.setTitle(newTitle, threadID, callback);
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
#### Example:
|
|
1003
|
+
|
|
1004
|
+
```javascript
|
|
1005
|
+
api.setTitle("New Chat Group", "1234567890", (err) => {
|
|
1006
|
+
if (err) {
|
|
1007
|
+
console.error("Change name error:", err);
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
console.log("Group name changed successfully!");
|
|
1011
|
+
});
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
---
|
|
1015
|
+
|
|
1016
|
+
### 3.8. addUserToGroup - Add Member to Group
|
|
1017
|
+
|
|
1018
|
+
Add user to group chat.
|
|
1019
|
+
|
|
1020
|
+
#### Syntax:
|
|
1021
|
+
```javascript
|
|
1022
|
+
api.addUserToGroup(userID, threadID, callback);
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
#### Example:
|
|
1026
|
+
|
|
1027
|
+
```javascript
|
|
1028
|
+
// Add 1 person
|
|
1029
|
+
api.addUserToGroup("100012345678901", "1234567890", (err) => {
|
|
1030
|
+
if (err) {
|
|
1031
|
+
console.error("Add user error:", err);
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
console.log("Member added successfully!");
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1037
|
+
// Add multiple people
|
|
1038
|
+
api.addUserToGroup(["100012345678901", "100012345678902"], "1234567890", (err) => {
|
|
1039
|
+
if (err) return console.error(err);
|
|
1040
|
+
console.log("Multiple members added!");
|
|
1041
|
+
});
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
---
|
|
1045
|
+
|
|
1046
|
+
### 3.9. removeUserFromGroup - Remove Member from Group
|
|
1047
|
+
|
|
1048
|
+
Remove user from group chat.
|
|
1049
|
+
|
|
1050
|
+
#### Syntax:
|
|
1051
|
+
```javascript
|
|
1052
|
+
api.removeUserFromGroup(userID, threadID, callback);
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
#### Example:
|
|
1056
|
+
|
|
1057
|
+
```javascript
|
|
1058
|
+
api.removeUserFromGroup("100012345678901", "1234567890", (err) => {
|
|
1059
|
+
if (err) {
|
|
1060
|
+
console.error("Remove user error:", err);
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
console.log("Member removed successfully!");
|
|
1064
|
+
});
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
---
|
|
1068
|
+
|
|
1069
|
+
### 3.10. changeNickname - Change Nickname
|
|
1070
|
+
|
|
1071
|
+
Change user's nickname in group chat.
|
|
1072
|
+
|
|
1073
|
+
#### Syntax:
|
|
1074
|
+
```javascript
|
|
1075
|
+
api.changeNickname(nickname, threadID, userID, callback);
|
|
1076
|
+
```
|
|
1077
|
+
|
|
1078
|
+
#### Example:
|
|
1079
|
+
|
|
1080
|
+
```javascript
|
|
1081
|
+
api.changeNickname("Admin Bot", "1234567890", "100012345678901", (err) => {
|
|
1082
|
+
if (err) {
|
|
1083
|
+
console.error("Change nickname error:", err);
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
console.log("Nickname changed successfully!");
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
// Remove nickname (set to original name)
|
|
1090
|
+
api.changeNickname("", "1234567890", "100012345678901", (err) => {
|
|
1091
|
+
if (err) return console.error(err);
|
|
1092
|
+
console.log("Nickname removed!");
|
|
1093
|
+
});
|
|
1094
|
+
```
|
|
1095
|
+
|
|
1096
|
+
---
|
|
1097
|
+
|
|
1098
|
+
### 3.11. markAsRead - Mark as Read
|
|
1099
|
+
|
|
1100
|
+
Mark message as read.
|
|
1101
|
+
|
|
1102
|
+
#### Syntax:
|
|
1103
|
+
```javascript
|
|
1104
|
+
api.markAsRead(threadID, callback);
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
#### Example:
|
|
1108
|
+
|
|
1109
|
+
```javascript
|
|
1110
|
+
api.listenMqtt((err, event) => {
|
|
1111
|
+
if (err) return console.error(err);
|
|
1112
|
+
|
|
1113
|
+
if (event.type === "message") {
|
|
1114
|
+
// Auto mark as read
|
|
1115
|
+
api.markAsRead(event.threadID, (err) => {
|
|
1116
|
+
if (err) console.error("Mark as read error:", err);
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
---
|
|
1123
|
+
|
|
1124
|
+
### 3.12. markAsDelivered - Mark as Delivered
|
|
1125
|
+
|
|
1126
|
+
Mark message as delivered.
|
|
1127
|
+
|
|
1128
|
+
#### Syntax:
|
|
1129
|
+
```javascript
|
|
1130
|
+
api.markAsDelivered(threadID, messageID, callback);
|
|
1131
|
+
```
|
|
1132
|
+
|
|
1133
|
+
#### Example:
|
|
1134
|
+
|
|
1135
|
+
```javascript
|
|
1136
|
+
api.markAsDelivered("1234567890", "mid.xxx", (err) => {
|
|
1137
|
+
if (err) {
|
|
1138
|
+
console.error("Mark as delivered error:", err);
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
console.log("Marked as delivered!");
|
|
1142
|
+
});
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
---
|
|
1146
|
+
|
|
1147
|
+
### 3.13. markAsReadAll - Mark All as Read
|
|
1148
|
+
|
|
1149
|
+
Mark all messages as read.
|
|
1150
|
+
|
|
1151
|
+
#### Syntax:
|
|
1152
|
+
```javascript
|
|
1153
|
+
api.markAsReadAll(callback);
|
|
1154
|
+
```
|
|
1155
|
+
|
|
1156
|
+
#### Example:
|
|
1157
|
+
|
|
1158
|
+
```javascript
|
|
1159
|
+
api.markAsReadAll((err) => {
|
|
1160
|
+
if (err) {
|
|
1161
|
+
console.error("Error:", err);
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
console.log("All messages marked as read!");
|
|
1165
|
+
});
|
|
1166
|
+
```
|
|
1167
|
+
|
|
1168
|
+
---
|
|
1169
|
+
|
|
1170
|
+
### 3.14. sendTypingIndicator - Show Typing Indicator
|
|
1171
|
+
|
|
1172
|
+
Display "typing..." status in chat.
|
|
1173
|
+
|
|
1174
|
+
#### Syntax:
|
|
1175
|
+
```javascript
|
|
1176
|
+
api.sendTypingIndicator(threadID, callback);
|
|
1177
|
+
```
|
|
1178
|
+
|
|
1179
|
+
#### Example:
|
|
1180
|
+
|
|
1181
|
+
```javascript
|
|
1182
|
+
// Show typing
|
|
1183
|
+
api.sendTypingIndicator("1234567890", (err) => {
|
|
1184
|
+
if (err) return console.error(err);
|
|
1185
|
+
|
|
1186
|
+
// After 3 seconds, send message
|
|
1187
|
+
setTimeout(() => {
|
|
1188
|
+
api.sendMessage("Hello!", "1234567890");
|
|
1189
|
+
}, 3000);
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
// Or stop typing indicator
|
|
1193
|
+
api.sendTypingIndicator("1234567890", (err) => {
|
|
1194
|
+
if (err) return console.error(err);
|
|
1195
|
+
}, true); // 3rd parameter is true to turn off typing
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
---
|
|
1199
|
+
|
|
1200
|
+
### 3.15. unsendMessage - Unsend Message
|
|
1201
|
+
|
|
1202
|
+
Unsend/recall a sent message.
|
|
1203
|
+
|
|
1204
|
+
#### Syntax:
|
|
1205
|
+
```javascript
|
|
1206
|
+
api.unsendMessage(messageID, callback);
|
|
1207
|
+
```
|
|
1208
|
+
|
|
1209
|
+
#### Example:
|
|
1210
|
+
|
|
1211
|
+
```javascript
|
|
1212
|
+
api.sendMessage("This message will be deleted", "1234567890", (err, messageInfo) => {
|
|
1213
|
+
if (err) return console.error(err);
|
|
1214
|
+
|
|
1215
|
+
// Unsend after 5 seconds
|
|
1216
|
+
setTimeout(() => {
|
|
1217
|
+
api.unsendMessage(messageInfo.messageID, (err) => {
|
|
1218
|
+
if (err) {
|
|
1219
|
+
console.error("Unsend error:", err);
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
console.log("Message unsent!");
|
|
1223
|
+
});
|
|
1224
|
+
}, 5000);
|
|
1225
|
+
});
|
|
1226
|
+
```
|
|
1227
|
+
|
|
1228
|
+
---
|
|
1229
|
+
|
|
1230
|
+
### 3.16. createPoll - Create Poll
|
|
1231
|
+
|
|
1232
|
+
Create poll in group chat.
|
|
1233
|
+
|
|
1234
|
+
#### Syntax:
|
|
1235
|
+
```javascript
|
|
1236
|
+
api.createPoll(title, threadID, options, callback);
|
|
1237
|
+
```
|
|
1238
|
+
|
|
1239
|
+
#### Example:
|
|
1240
|
+
|
|
1241
|
+
```javascript
|
|
1242
|
+
const title = "Choose travel destination?";
|
|
1243
|
+
const options = {
|
|
1244
|
+
"Da Lat": false, // false = allow multiple choices
|
|
1245
|
+
"Nha Trang": false,
|
|
1246
|
+
"Phu Quoc": false
|
|
1247
|
+
};
|
|
1248
|
+
|
|
1249
|
+
api.createPoll(title, "1234567890", options, (err, pollInfo) => {
|
|
1250
|
+
if (err) {
|
|
1251
|
+
console.error("Create poll error:", err);
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
console.log("Poll created successfully!");
|
|
1255
|
+
});
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
---
|
|
1259
|
+
|
|
1260
|
+
### 3.17. handleMessageRequest - Handle Message Request
|
|
1261
|
+
|
|
1262
|
+
Accept or decline message from stranger.
|
|
1263
|
+
|
|
1264
|
+
#### Syntax:
|
|
1265
|
+
```javascript
|
|
1266
|
+
api.handleMessageRequest(threadID, accept, callback);
|
|
1267
|
+
```
|
|
1268
|
+
|
|
1269
|
+
#### Example:
|
|
1270
|
+
|
|
1271
|
+
```javascript
|
|
1272
|
+
// Accept message
|
|
1273
|
+
api.handleMessageRequest("1234567890", true, (err) => {
|
|
1274
|
+
if (err) {
|
|
1275
|
+
console.error("Error:", err);
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
console.log("Message accepted!");
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
// Decline message
|
|
1282
|
+
api.handleMessageRequest("1234567890", false, (err) => {
|
|
1283
|
+
if (err) return console.error(err);
|
|
1284
|
+
console.log("Message declined!");
|
|
1285
|
+
});
|
|
1286
|
+
```
|
|
1287
|
+
|
|
1288
|
+
---
|
|
1289
|
+
|
|
1290
|
+
### 3.18. muteThread - Mute Notifications
|
|
1291
|
+
|
|
1292
|
+
Mute or unmute notifications for conversation.
|
|
1293
|
+
|
|
1294
|
+
#### Syntax:
|
|
1295
|
+
```javascript
|
|
1296
|
+
api.muteThread(threadID, muteSeconds, callback);
|
|
1297
|
+
```
|
|
1298
|
+
|
|
1299
|
+
#### Example:
|
|
1300
|
+
|
|
1301
|
+
```javascript
|
|
1302
|
+
// Mute for 1 hour (3600 seconds)
|
|
1303
|
+
api.muteThread("1234567890", 3600, (err) => {
|
|
1304
|
+
if (err) {
|
|
1305
|
+
console.error("Error:", err);
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
console.log("Muted for 1 hour!");
|
|
1309
|
+
});
|
|
1310
|
+
|
|
1311
|
+
// Mute permanently
|
|
1312
|
+
api.muteThread("1234567890", -1, (err) => {
|
|
1313
|
+
if (err) return console.error(err);
|
|
1314
|
+
console.log("Muted permanently!");
|
|
1315
|
+
});
|
|
1316
|
+
|
|
1317
|
+
// Unmute
|
|
1318
|
+
api.muteThread("1234567890", 0, (err) => {
|
|
1319
|
+
if (err) return console.error(err);
|
|
1320
|
+
console.log("Unmuted!");
|
|
1321
|
+
});
|
|
1322
|
+
```
|
|
1323
|
+
|
|
1324
|
+
---
|
|
1325
|
+
|
|
1326
|
+
### 3.19. getThreadList - Get Thread List
|
|
1327
|
+
|
|
1328
|
+
Get list of conversations.
|
|
1329
|
+
|
|
1330
|
+
#### Syntax:
|
|
1331
|
+
```javascript
|
|
1332
|
+
api.getThreadList(limit, timestamp, tags, callback);
|
|
1333
|
+
```
|
|
1334
|
+
|
|
1335
|
+
#### Example:
|
|
1336
|
+
|
|
1337
|
+
```javascript
|
|
1338
|
+
// Get 20 most recent conversations
|
|
1339
|
+
api.getThreadList(20, null, ["INBOX"], (err, threads) => {
|
|
1340
|
+
if (err) {
|
|
1341
|
+
console.error("Error:", err);
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
threads.forEach(thread => {
|
|
1346
|
+
console.log("Thread ID:", thread.threadID);
|
|
1347
|
+
console.log("Name:", thread.name);
|
|
1348
|
+
console.log("Unread count:", thread.unreadCount);
|
|
1349
|
+
console.log("Last message:", thread.snippet);
|
|
1350
|
+
console.log("---");
|
|
1351
|
+
});
|
|
1352
|
+
});
|
|
1353
|
+
|
|
1354
|
+
// Tags can be:
|
|
1355
|
+
// - "INBOX" : Inbox
|
|
1356
|
+
// - "ARCHIVED" : Archived
|
|
1357
|
+
// - "PENDING" : Pending messages
|
|
1358
|
+
// - "OTHER" : Other
|
|
1359
|
+
```
|
|
1360
|
+
|
|
1361
|
+
---
|
|
1362
|
+
|
|
1363
|
+
### 3.20. getThreadHistory - Get Message History
|
|
1364
|
+
|
|
1365
|
+
Get message history of conversation.
|
|
1366
|
+
|
|
1367
|
+
#### Syntax:
|
|
1368
|
+
```javascript
|
|
1369
|
+
api.getThreadHistory(threadID, amount, timestamp, callback);
|
|
1370
|
+
```
|
|
1371
|
+
|
|
1372
|
+
#### Example:
|
|
1373
|
+
|
|
1374
|
+
```javascript
|
|
1375
|
+
// Get 50 most recent messages
|
|
1376
|
+
api.getThreadHistory("1234567890", 50, null, (err, history) => {
|
|
1377
|
+
if (err) {
|
|
1378
|
+
console.error("Error:", err);
|
|
1379
|
+
return;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
history.forEach(msg => {
|
|
1383
|
+
console.log("From:", msg.senderName);
|
|
1384
|
+
console.log("Content:", msg.body);
|
|
1385
|
+
console.log("Time:", new Date(msg.timestamp));
|
|
1386
|
+
console.log("---");
|
|
1387
|
+
});
|
|
1388
|
+
});
|
|
1389
|
+
|
|
1390
|
+
// Get older messages (pagination)
|
|
1391
|
+
const oldestTimestamp = history[history.length - 1].timestamp;
|
|
1392
|
+
api.getThreadHistory("1234567890", 50, oldestTimestamp, (err, olderHistory) => {
|
|
1393
|
+
if (err) return console.error(err);
|
|
1394
|
+
console.log("Retrieved 50 older messages!");
|
|
1395
|
+
});
|
|
1396
|
+
```
|
|
1397
|
+
|
|
1398
|
+
---
|
|
1399
|
+
|
|
1400
|
+
### 3.21. getThreadPictures - Get Thread Pictures
|
|
1401
|
+
|
|
1402
|
+
Get conversation/group avatar URL.
|
|
1403
|
+
|
|
1404
|
+
#### Syntax:
|
|
1405
|
+
```javascript
|
|
1406
|
+
api.getThreadPictures(threadID, offset, limit, callback);
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
#### Example:
|
|
1410
|
+
|
|
1411
|
+
```javascript
|
|
1412
|
+
api.getThreadPictures("1234567890", 0, 10, (err, pictures) => {
|
|
1413
|
+
if (err) {
|
|
1414
|
+
console.error("Error:", err);
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
pictures.forEach(pic => {
|
|
1419
|
+
console.log("Image URL:", pic.url);
|
|
1420
|
+
console.log("Width:", pic.width);
|
|
1421
|
+
console.log("Height:", pic.height);
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
```
|
|
1425
|
+
|
|
1426
|
+
---
|
|
1427
|
+
|
|
1428
|
+
### 3.22. getUserID - Get User ID
|
|
1429
|
+
|
|
1430
|
+
Get User ID from username or profile URL.
|
|
1431
|
+
|
|
1432
|
+
#### Syntax:
|
|
1433
|
+
```javascript
|
|
1434
|
+
api.getUserID(name, callback);
|
|
1435
|
+
```
|
|
1436
|
+
|
|
1437
|
+
#### Example:
|
|
1438
|
+
|
|
1439
|
+
```javascript
|
|
1440
|
+
// From username
|
|
1441
|
+
api.getUserID("john.doe", (err, data) => {
|
|
1442
|
+
if (err) {
|
|
1443
|
+
console.error("Error:", err);
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
console.log("User ID:", data.userID);
|
|
1447
|
+
});
|
|
1448
|
+
|
|
1449
|
+
// From profile URL
|
|
1450
|
+
api.getUserID("https://facebook.com/john.doe", (err, data) => {
|
|
1451
|
+
if (err) return console.error(err);
|
|
1452
|
+
console.log("User ID:", data.userID);
|
|
1453
|
+
});
|
|
1454
|
+
```
|
|
1455
|
+
|
|
1456
|
+
---
|
|
1457
|
+
|
|
1458
|
+
### 3.23. getAppState - Get Current AppState
|
|
1459
|
+
|
|
1460
|
+
Get current AppState (cookies, session).
|
|
1461
|
+
|
|
1462
|
+
#### Syntax:
|
|
1463
|
+
```javascript
|
|
1464
|
+
const appState = api.getAppState();
|
|
1465
|
+
```
|
|
1466
|
+
|
|
1467
|
+
#### Example:
|
|
1468
|
+
|
|
1469
|
+
```javascript
|
|
1470
|
+
const fs = require("fs");
|
|
1471
|
+
|
|
1472
|
+
// Get and save AppState
|
|
1473
|
+
const appState = api.getAppState();
|
|
1474
|
+
fs.writeFileSync("appstate.json", JSON.stringify(appState, null, 2));
|
|
1475
|
+
console.log("✅ AppState saved!");
|
|
1476
|
+
|
|
1477
|
+
// Periodically update AppState (every 10 minutes)
|
|
1478
|
+
setInterval(() => {
|
|
1479
|
+
const updatedAppState = api.getAppState();
|
|
1480
|
+
fs.writeFileSync("appstate.json", JSON.stringify(updatedAppState, null, 2));
|
|
1481
|
+
console.log("🔄 AppState updated");
|
|
1482
|
+
}, 10 * 60 * 1000);
|
|
1483
|
+
```
|
|
1484
|
+
|
|
1485
|
+
---
|
|
1486
|
+
|
|
1487
|
+
### 3.24. deleteMessage - Delete Message (from your side)
|
|
1488
|
+
|
|
1489
|
+
Delete message from your side (not unsend).
|
|
1490
|
+
|
|
1491
|
+
#### Syntax:
|
|
1492
|
+
```javascript
|
|
1493
|
+
api.deleteMessage(messageID, callback);
|
|
1494
|
+
```
|
|
1495
|
+
|
|
1496
|
+
#### Example:
|
|
1497
|
+
|
|
1498
|
+
```javascript
|
|
1499
|
+
api.deleteMessage("mid.xxx", (err) => {
|
|
1500
|
+
if (err) {
|
|
1501
|
+
console.error("Delete message error:", err);
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
console.log("Message deleted!");
|
|
1505
|
+
});
|
|
1506
|
+
```
|
|
1507
|
+
|
|
1508
|
+
---
|
|
1509
|
+
|
|
1510
|
+
### 3.25. deleteThread - Delete Thread
|
|
1511
|
+
|
|
1512
|
+
Delete conversation from your list.
|
|
1513
|
+
|
|
1514
|
+
#### Syntax:
|
|
1515
|
+
```javascript
|
|
1516
|
+
api.deleteThread(threadID, callback);
|
|
1517
|
+
```
|
|
1518
|
+
|
|
1519
|
+
#### Example:
|
|
1520
|
+
|
|
1521
|
+
```javascript
|
|
1522
|
+
api.deleteThread("1234567890", (err) => {
|
|
1523
|
+
if (err) {
|
|
1524
|
+
console.error("Delete thread error:", err);
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
console.log("Thread deleted!");
|
|
1528
|
+
});
|
|
1529
|
+
```
|
|
1530
|
+
|
|
1531
|
+
---
|
|
1532
|
+
|
|
1533
|
+
### 3.26. forwardAttachment - Forward Attachment
|
|
1534
|
+
|
|
1535
|
+
Forward attachment from one message to another.
|
|
1536
|
+
|
|
1537
|
+
#### Syntax:
|
|
1538
|
+
```javascript
|
|
1539
|
+
api.forwardAttachment(attachmentID, userOrThreadID, callback);
|
|
1540
|
+
```
|
|
1541
|
+
|
|
1542
|
+
#### Example:
|
|
1543
|
+
|
|
1544
|
+
```javascript
|
|
1545
|
+
api.listenMqtt((err, event) => {
|
|
1546
|
+
if (err) return console.error(err);
|
|
1547
|
+
|
|
1548
|
+
if (event.type === "message" && event.attachments.length > 0) {
|
|
1549
|
+
// Forward first attachment
|
|
1550
|
+
const attachmentID = event.attachments[0].ID;
|
|
1551
|
+
|
|
1552
|
+
api.forwardAttachment(attachmentID, "100012345678901", (err) => {
|
|
1553
|
+
if (err) {
|
|
1554
|
+
console.error("Forward error:", err);
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
console.log("Attachment forwarded!");
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
});
|
|
1561
|
+
```
|
|
1562
|
+
|
|
1563
|
+
---
|
|
1564
|
+
|
|
1565
|
+
### 3.27. setMessageReaction - React to Message
|
|
1566
|
+
|
|
1567
|
+
Add reaction (like, love, haha, wow, sad, angry) to message.
|
|
1568
|
+
|
|
1569
|
+
#### Syntax:
|
|
1570
|
+
```javascript
|
|
1571
|
+
api.setMessageReaction(reaction, messageID, callback);
|
|
1572
|
+
```
|
|
1573
|
+
|
|
1574
|
+
#### Example:
|
|
1575
|
+
|
|
1576
|
+
```javascript
|
|
1577
|
+
// Reaction can be:
|
|
1578
|
+
// "👍" or ":like:" - Like
|
|
1579
|
+
// "❤️" or ":love:" - Love
|
|
1580
|
+
// "😂" or ":haha:" - Haha
|
|
1581
|
+
// "😮" or ":wow:" - Wow
|
|
1582
|
+
// "😢" or ":sad:" - Sad
|
|
1583
|
+
// "😠" or ":angry:" - Angry
|
|
1584
|
+
// "" (empty string) - Remove reaction
|
|
1585
|
+
|
|
1586
|
+
api.listenMqtt((err, event) => {
|
|
1587
|
+
if (err) return console.error(err);
|
|
1588
|
+
|
|
1589
|
+
if (event.type === "message" && event.body === "React me") {
|
|
1590
|
+
api.setMessageReaction("❤️", event.messageID, (err) => {
|
|
1591
|
+
if (err) {
|
|
1592
|
+
console.error("React error:", err);
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
console.log("Message reacted!");
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
});
|
|
1599
|
+
|
|
1600
|
+
// Remove reaction
|
|
1601
|
+
api.setMessageReaction("", "mid.xxx", (err) => {
|
|
1602
|
+
if (err) return console.error(err);
|
|
1603
|
+
console.log("Reaction removed!");
|
|
1604
|
+
});
|
|
1605
|
+
```
|
|
1606
|
+
|
|
1607
|
+
---
|
|
1608
|
+
|
|
1609
|
+
### 3.28. searchForThread - Search for Thread
|
|
1610
|
+
|
|
1611
|
+
Search for conversation by name.
|
|
1612
|
+
|
|
1613
|
+
#### Syntax:
|
|
1614
|
+
```javascript
|
|
1615
|
+
api.searchForThread(name, callback);
|
|
1616
|
+
```
|
|
1617
|
+
|
|
1618
|
+
#### Example:
|
|
1619
|
+
|
|
1620
|
+
```javascript
|
|
1621
|
+
api.searchForThread("Study Group", (err, threads) => {
|
|
1622
|
+
if (err) {
|
|
1623
|
+
console.error("Search error:", err);
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
threads.forEach(thread => {
|
|
1628
|
+
console.log("Name:", thread.name);
|
|
1629
|
+
console.log("Thread ID:", thread.threadID);
|
|
1630
|
+
console.log("Type:", thread.isGroup ? "Group" : "Personal");
|
|
1631
|
+
console.log("---");
|
|
1632
|
+
});
|
|
1633
|
+
});
|
|
1634
|
+
```
|
|
1635
|
+
|
|
1636
|
+
---
|
|
1637
|
+
|
|
1638
|
+
### 3.29. logout - Logout
|
|
1639
|
+
|
|
1640
|
+
Logout from Facebook account.
|
|
1641
|
+
|
|
1642
|
+
#### Syntax:
|
|
1643
|
+
```javascript
|
|
1644
|
+
api.logout(callback);
|
|
1645
|
+
```
|
|
1646
|
+
|
|
1647
|
+
#### Example:
|
|
1648
|
+
|
|
1649
|
+
```javascript
|
|
1650
|
+
api.logout((err) => {
|
|
1651
|
+
if (err) {
|
|
1652
|
+
console.error("Logout error:", err);
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
console.log("Logged out successfully!");
|
|
1656
|
+
});
|
|
1657
|
+
```
|
|
1658
|
+
|
|
1659
|
+
---
|
|
1660
|
+
|
|
1661
|
+
### 3.30. getCurrentUserID - Get Current User ID
|
|
1662
|
+
|
|
1663
|
+
Get User ID of currently logged in account.
|
|
1664
|
+
|
|
1665
|
+
#### Syntax:
|
|
1666
|
+
```javascript
|
|
1667
|
+
const myUserID = api.getCurrentUserID();
|
|
1668
|
+
```
|
|
1669
|
+
|
|
1670
|
+
#### Example:
|
|
1671
|
+
|
|
1672
|
+
```javascript
|
|
1673
|
+
const myUserID = api.getCurrentUserID();
|
|
1674
|
+
console.log("Bot's User ID:", myUserID);
|
|
1675
|
+
|
|
1676
|
+
// Use to check if message is from bot
|
|
1677
|
+
api.listenMqtt((err, event) => {
|
|
1678
|
+
if (err) return console.error(err);
|
|
1679
|
+
|
|
1680
|
+
if (event.type === "message") {
|
|
1681
|
+
if (event.senderID === myUserID) {
|
|
1682
|
+
console.log("This is a message from bot!");
|
|
1683
|
+
} else {
|
|
1684
|
+
console.log("Message from someone else");
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
});
|
|
1688
|
+
```
|
|
1689
|
+
|
|
1690
|
+
---
|
|
1691
|
+
|
|
1692
|
+
### 3.31. resolvePhotoUrl - Get High Quality Photo URL
|
|
1693
|
+
|
|
1694
|
+
Get high resolution photo URL from photo ID.
|
|
1695
|
+
|
|
1696
|
+
#### Syntax:
|
|
1697
|
+
```javascript
|
|
1698
|
+
api.resolvePhotoUrl(photoID, callback);
|
|
1699
|
+
```
|
|
1700
|
+
|
|
1701
|
+
#### Example:
|
|
1702
|
+
|
|
1703
|
+
```javascript
|
|
1704
|
+
api.resolvePhotoUrl("1234567890123456", (err, url) => {
|
|
1705
|
+
if (err) {
|
|
1706
|
+
console.error("Error:", err);
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
console.log("High quality image URL:", url);
|
|
1710
|
+
});
|
|
1711
|
+
```
|
|
1712
|
+
|
|
1713
|
+
---
|
|
1714
|
+
|
|
1715
|
+
### 3.32. changeArchivedStatus - Archive/Unarchive Thread
|
|
1716
|
+
|
|
1717
|
+
Archive or unarchive conversation.
|
|
1718
|
+
|
|
1719
|
+
#### Syntax:
|
|
1720
|
+
```javascript
|
|
1721
|
+
api.changeArchivedStatus(threadID, archive, callback);
|
|
1722
|
+
```
|
|
1723
|
+
|
|
1724
|
+
#### Example:
|
|
1725
|
+
|
|
1726
|
+
```javascript
|
|
1727
|
+
// Archive conversation
|
|
1728
|
+
api.changeArchivedStatus("1234567890", true, (err) => {
|
|
1729
|
+
if (err) {
|
|
1730
|
+
console.error("Error:", err);
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
console.log("Thread archived!");
|
|
1734
|
+
});
|
|
1735
|
+
|
|
1736
|
+
// Unarchive
|
|
1737
|
+
api.changeArchivedStatus("1234567890", false, (err) => {
|
|
1738
|
+
if (err) return console.error(err);
|
|
1739
|
+
console.log("Thread unarchived!");
|
|
1740
|
+
});
|
|
1741
|
+
```
|
|
1742
|
+
|
|
1743
|
+
---
|
|
1744
|
+
|
|
1745
|
+
### 3.33. changeBlockedStatus - Block/Unblock User
|
|
1746
|
+
|
|
1747
|
+
Block or unblock user.
|
|
1748
|
+
|
|
1749
|
+
#### Syntax:
|
|
1750
|
+
```javascript
|
|
1751
|
+
api.changeBlockedStatus(userID, block, callback);
|
|
1752
|
+
```
|
|
1753
|
+
|
|
1754
|
+
#### Example:
|
|
1755
|
+
|
|
1756
|
+
```javascript
|
|
1757
|
+
// Block user
|
|
1758
|
+
api.changeBlockedStatus("100012345678901", true, (err) => {
|
|
1759
|
+
if (err) {
|
|
1760
|
+
console.error("Error:", err);
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
console.log("User blocked!");
|
|
1764
|
+
});
|
|
1765
|
+
|
|
1766
|
+
// Unblock
|
|
1767
|
+
api.changeBlockedStatus("100012345678901", false, (err) => {
|
|
1768
|
+
if (err) return console.error(err);
|
|
1769
|
+
console.log("User unblocked!");
|
|
1770
|
+
});
|
|
1771
|
+
```
|
|
1772
|
+
|
|
1773
|
+
---
|
|
1774
|
+
|
|
1775
|
+
### 3.34. createNewGroup - Create New Group
|
|
1776
|
+
|
|
1777
|
+
Create new group chat with member list.
|
|
1778
|
+
|
|
1779
|
+
#### Syntax:
|
|
1780
|
+
```javascript
|
|
1781
|
+
api.createNewGroup(participantIDs, groupTitle, callback);
|
|
1782
|
+
```
|
|
1783
|
+
|
|
1784
|
+
#### Example:
|
|
1785
|
+
|
|
1786
|
+
```javascript
|
|
1787
|
+
const members = ["100012345678901", "100012345678902", "100012345678903"];
|
|
1788
|
+
const groupName = "New Chat Group";
|
|
1789
|
+
|
|
1790
|
+
api.createNewGroup(members, groupName, (err, threadID) => {
|
|
1791
|
+
if (err) {
|
|
1792
|
+
console.error("Create group error:", err);
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
console.log("Group created successfully!");
|
|
1796
|
+
console.log("Thread ID:", threadID);
|
|
1797
|
+
|
|
1798
|
+
// Send message to new group
|
|
1799
|
+
api.sendMessage("Welcome to the group!", threadID);
|
|
1800
|
+
});
|
|
1801
|
+
```
|
|
1802
|
+
|
|
1803
|
+
---
|
|
1804
|
+
|
|
1805
|
+
## 4. COMPLETE BOT EXAMPLES
|
|
1806
|
+
|
|
1807
|
+
### 4.1. Echo Bot (Message Repeater)
|
|
1808
|
+
|
|
1809
|
+
```javascript
|
|
1810
|
+
const fs = require("fs");
|
|
1811
|
+
const login = require("surya-sahil-fca");
|
|
1812
|
+
|
|
1813
|
+
// Login
|
|
1814
|
+
login(
|
|
1815
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
|
1816
|
+
(err, api) => {
|
|
1817
|
+
if (err) {
|
|
1818
|
+
console.error("Login error:", err);
|
|
1819
|
+
return;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
console.log("✅ Bot started!");
|
|
1823
|
+
|
|
1824
|
+
// Configuration
|
|
1825
|
+
api.setOptions({
|
|
1826
|
+
listenEvents: true,
|
|
1827
|
+
selfListen: false,
|
|
1828
|
+
logLevel: "silent"
|
|
1829
|
+
});
|
|
1830
|
+
|
|
1831
|
+
// Listen for messages
|
|
1832
|
+
api.listenMqtt((err, event) => {
|
|
1833
|
+
if (err) return console.error(err);
|
|
1834
|
+
|
|
1835
|
+
if (event.type === "message") {
|
|
1836
|
+
const { body, threadID, messageID, senderID } = event;
|
|
1837
|
+
|
|
1838
|
+
// Stop bot command
|
|
1839
|
+
if (body === "/stop") {
|
|
1840
|
+
api.sendMessage("Bot stopped!", threadID);
|
|
1841
|
+
process.exit(0);
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
// Echo message
|
|
1845
|
+
api.sendMessage(`📣 Echo: ${body}`, threadID, messageID);
|
|
1846
|
+
}
|
|
1847
|
+
});
|
|
1848
|
+
}
|
|
1849
|
+
);
|
|
1850
|
+
```
|
|
1851
|
+
|
|
1852
|
+
---
|
|
1853
|
+
|
|
1854
|
+
### 4.2. Group Management Bot
|
|
1855
|
+
|
|
1856
|
+
```javascript
|
|
1857
|
+
const fs = require("fs");
|
|
1858
|
+
const login = require("surya-sahil-fca");
|
|
1859
|
+
|
|
1860
|
+
// Admin list (User IDs)
|
|
1861
|
+
const ADMINS = ["100012345678901", "100012345678902"];
|
|
1862
|
+
|
|
1863
|
+
// Check admin permission
|
|
1864
|
+
function isAdmin(userID) {
|
|
1865
|
+
return ADMINS.includes(userID);
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
login(
|
|
1869
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
|
1870
|
+
(err, api) => {
|
|
1871
|
+
if (err) return console.error(err);
|
|
1872
|
+
|
|
1873
|
+
console.log("✅ Group management bot started!");
|
|
1874
|
+
|
|
1875
|
+
api.setOptions({ listenEvents: true });
|
|
1876
|
+
|
|
1877
|
+
api.listenMqtt((err, event) => {
|
|
1878
|
+
if (err) return console.error(err);
|
|
1879
|
+
|
|
1880
|
+
const { type, threadID, senderID, body, messageID } = event;
|
|
1881
|
+
|
|
1882
|
+
// Handle messages
|
|
1883
|
+
if (type === "message") {
|
|
1884
|
+
// Only admins can use commands
|
|
1885
|
+
if (!isAdmin(senderID)) {
|
|
1886
|
+
if (body.startsWith("/")) {
|
|
1887
|
+
api.sendMessage(
|
|
1888
|
+
"❌ You don't have permission to use this command!",
|
|
1889
|
+
threadID,
|
|
1890
|
+
messageID
|
|
1891
|
+
);
|
|
1892
|
+
}
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
// Kick command
|
|
1897
|
+
if (body.startsWith("/kick ")) {
|
|
1898
|
+
const userID = body.split(" ")[1];
|
|
1899
|
+
api.removeUserFromGroup(userID, threadID, (err) => {
|
|
1900
|
+
if (err) {
|
|
1901
|
+
api.sendMessage("❌ Error kicking user!", threadID);
|
|
1902
|
+
} else {
|
|
1903
|
+
api.sendMessage("✅ User kicked!", threadID);
|
|
1904
|
+
}
|
|
1905
|
+
});
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
// Rename command
|
|
1909
|
+
else if (body.startsWith("/rename ")) {
|
|
1910
|
+
const newName = body.substring(8);
|
|
1911
|
+
api.setTitle(newName, threadID, (err) => {
|
|
1912
|
+
if (err) {
|
|
1913
|
+
api.sendMessage("❌ Error renaming group!", threadID);
|
|
1914
|
+
} else {
|
|
1915
|
+
api.sendMessage(`✅ Group renamed to: ${newName}`, threadID);
|
|
1916
|
+
}
|
|
1917
|
+
});
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
// Group info command
|
|
1921
|
+
else if (body === "/info") {
|
|
1922
|
+
api.getThreadInfo(threadID, (err, info) => {
|
|
1923
|
+
if (err) return api.sendMessage("❌ Error getting info!", threadID);
|
|
1924
|
+
|
|
1925
|
+
const message = `
|
|
1926
|
+
📊 GROUP INFORMATION
|
|
1927
|
+
━━━━━━━━━━━━━━━
|
|
1928
|
+
👥 Name: ${info.threadName}
|
|
1929
|
+
📝 Members: ${info.participantIDs.length}
|
|
1930
|
+
👑 Admins: ${info.adminIDs.length}
|
|
1931
|
+
🎨 Color: ${info.color}
|
|
1932
|
+
😊 Emoji: ${info.emoji || "Default"}
|
|
1933
|
+
`.trim();
|
|
1934
|
+
|
|
1935
|
+
api.sendMessage(message, threadID);
|
|
1936
|
+
});
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
// Help command
|
|
1940
|
+
else if (body === "/help") {
|
|
1941
|
+
const helpMessage = `
|
|
1942
|
+
🤖 COMMAND LIST
|
|
1943
|
+
━━━━━━━━━━━━━━━
|
|
1944
|
+
/kick [userID] - Kick member
|
|
1945
|
+
/rename [new name] - Rename group
|
|
1946
|
+
/info - View group info
|
|
1947
|
+
/help - Show help
|
|
1948
|
+
`.trim();
|
|
1949
|
+
|
|
1950
|
+
api.sendMessage(helpMessage, threadID);
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
// Handle events
|
|
1955
|
+
else if (type === "event") {
|
|
1956
|
+
// Welcome new members
|
|
1957
|
+
if (event.logMessageType === "log:subscribe") {
|
|
1958
|
+
const addedUsers = event.logMessageData.addedParticipants;
|
|
1959
|
+
addedUsers.forEach(user => {
|
|
1960
|
+
api.sendMessage(
|
|
1961
|
+
`👋 Welcome ${user.fullName} to the group!`,
|
|
1962
|
+
threadID
|
|
1963
|
+
);
|
|
1964
|
+
});
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
// Notify when someone leaves
|
|
1968
|
+
else if (event.logMessageType === "log:unsubscribe") {
|
|
1969
|
+
api.sendMessage(`👋 Goodbye! A member left the group.`, threadID);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
);
|
|
1975
|
+
```
|
|
1976
|
+
|
|
1977
|
+
---
|
|
1978
|
+
|
|
1979
|
+
### 4.3. AI ChatBot Style (Mock)
|
|
1980
|
+
|
|
1981
|
+
```javascript
|
|
1982
|
+
const fs = require("fs");
|
|
1983
|
+
const login = require("surya-sahil-fca");
|
|
1984
|
+
|
|
1985
|
+
// Store chat history by threadID
|
|
1986
|
+
const chatHistory = {};
|
|
1987
|
+
|
|
1988
|
+
// Mock AI response function
|
|
1989
|
+
function getAIResponse(message, threadID) {
|
|
1990
|
+
// Initialize history if not exists
|
|
1991
|
+
if (!chatHistory[threadID]) {
|
|
1992
|
+
chatHistory[threadID] = [];
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
// Add user message to history
|
|
1996
|
+
chatHistory[threadID].push({ role: "user", content: message });
|
|
1997
|
+
|
|
1998
|
+
// Limit history to last 10 messages
|
|
1999
|
+
if (chatHistory[threadID].length > 10) {
|
|
2000
|
+
chatHistory[threadID] = chatHistory[threadID].slice(-10);
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
// Mock response (you can integrate real ChatGPT API here)
|
|
2004
|
+
let response = "";
|
|
2005
|
+
|
|
2006
|
+
if (message.toLowerCase().includes("hello")) {
|
|
2007
|
+
response = "Hello! How can I help you?";
|
|
2008
|
+
} else if (message.toLowerCase().includes("name")) {
|
|
2009
|
+
response = "I'm an AI Assistant Bot!";
|
|
2010
|
+
} else if (message.toLowerCase().includes("weather")) {
|
|
2011
|
+
response = "Sorry, I don't have weather information. Please check weather apps!";
|
|
2012
|
+
} else {
|
|
2013
|
+
response = `I received your message: "${message}". Thank you for chatting with me!`;
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
// Add response to history
|
|
2017
|
+
chatHistory[threadID].push({ role: "assistant", content: response });
|
|
2018
|
+
|
|
2019
|
+
return response;
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
login(
|
|
2023
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
|
2024
|
+
(err, api) => {
|
|
2025
|
+
if (err) return console.error(err);
|
|
2026
|
+
|
|
2027
|
+
console.log("✅ AI Bot started!");
|
|
2028
|
+
|
|
2029
|
+
api.setOptions({
|
|
2030
|
+
listenEvents: true,
|
|
2031
|
+
selfListen: false
|
|
2032
|
+
});
|
|
2033
|
+
|
|
2034
|
+
api.listenMqtt((err, event) => {
|
|
2035
|
+
if (err) return console.error(err);
|
|
2036
|
+
|
|
2037
|
+
if (event.type === "message" && event.body) {
|
|
2038
|
+
const { body, threadID, messageID } = event;
|
|
2039
|
+
|
|
2040
|
+
// Ignore if doesn't start with "ai" prefix
|
|
2041
|
+
if (!body.toLowerCase().startsWith("ai ")) {
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
// Get message content (remove "ai " prefix)
|
|
2046
|
+
const userMessage = body.substring(3).trim();
|
|
2047
|
+
|
|
2048
|
+
// Show typing indicator
|
|
2049
|
+
api.sendTypingIndicator(threadID);
|
|
2050
|
+
|
|
2051
|
+
// Delay for more natural feel
|
|
2052
|
+
setTimeout(() => {
|
|
2053
|
+
const aiResponse = getAIResponse(userMessage, threadID);
|
|
2054
|
+
api.sendMessage(`🤖 ${aiResponse}`, threadID, messageID);
|
|
2055
|
+
}, 1500);
|
|
2056
|
+
}
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
2059
|
+
);
|
|
2060
|
+
```
|
|
2061
|
+
|
|
2062
|
+
---
|
|
2063
|
+
|
|
2064
|
+
### 4.4. Auto-Reply Bot with Keywords
|
|
2065
|
+
|
|
2066
|
+
```javascript
|
|
2067
|
+
const fs = require("fs");
|
|
2068
|
+
const login = require("surya-sahil-fca");
|
|
2069
|
+
|
|
2070
|
+
// Auto-reply dictionary
|
|
2071
|
+
const autoReplies = {
|
|
2072
|
+
"hello": "Hi there! How can I help you?",
|
|
2073
|
+
"hi": "Hello! What's up?",
|
|
2074
|
+
"bye": "Goodbye! See you later!",
|
|
2075
|
+
"thanks": "You're welcome! 😊",
|
|
2076
|
+
"help": "I'm here to assist! Just ask me anything.",
|
|
2077
|
+
"time": () => `Current time: ${new Date().toLocaleTimeString()}`,
|
|
2078
|
+
"date": () => `Today's date: ${new Date().toLocaleDateString()}`
|
|
2079
|
+
};
|
|
2080
|
+
|
|
2081
|
+
function getAutoReply(message) {
|
|
2082
|
+
const lowerMessage = message.toLowerCase().trim();
|
|
2083
|
+
|
|
2084
|
+
// Check for exact matches
|
|
2085
|
+
for (let keyword in autoReplies) {
|
|
2086
|
+
if (lowerMessage.includes(keyword)) {
|
|
2087
|
+
const reply = autoReplies[keyword];
|
|
2088
|
+
// If reply is function, execute it
|
|
2089
|
+
return typeof reply === 'function' ? reply() : reply;
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
return null; // No match found
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
login(
|
|
2097
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
|
2098
|
+
(err, api) => {
|
|
2099
|
+
if (err) return console.error(err);
|
|
2100
|
+
|
|
2101
|
+
console.log("✅ Auto-reply bot started!");
|
|
2102
|
+
|
|
2103
|
+
api.setOptions({
|
|
2104
|
+
listenEvents: true,
|
|
2105
|
+
selfListen: false
|
|
2106
|
+
});
|
|
2107
|
+
|
|
2108
|
+
api.listenMqtt((err, event) => {
|
|
2109
|
+
if (err) return console.error(err);
|
|
2110
|
+
|
|
2111
|
+
if (event.type === "message" && event.body) {
|
|
2112
|
+
const { body, threadID, messageID } = event;
|
|
2113
|
+
|
|
2114
|
+
const reply = getAutoReply(body);
|
|
2115
|
+
|
|
2116
|
+
if (reply) {
|
|
2117
|
+
api.sendMessage(reply, threadID, messageID);
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2122
|
+
);
|
|
2123
|
+
```
|
|
2124
|
+
|
|
2125
|
+
---
|
|
2126
|
+
|
|
2127
|
+
### 4.5. Command Handler Bot
|
|
2128
|
+
|
|
2129
|
+
```javascript
|
|
2130
|
+
const fs = require("fs");
|
|
2131
|
+
const login = require("surya-sahil-fca");
|
|
2132
|
+
|
|
2133
|
+
// Command prefix
|
|
2134
|
+
const PREFIX = "/";
|
|
2135
|
+
|
|
2136
|
+
// Commands object
|
|
2137
|
+
const commands = {
|
|
2138
|
+
ping: {
|
|
2139
|
+
description: "Check bot latency",
|
|
2140
|
+
execute: (api, event) => {
|
|
2141
|
+
const start = Date.now();
|
|
2142
|
+
api.sendMessage("Pong! 🏓", event.threadID, (err) => {
|
|
2143
|
+
if (!err) {
|
|
2144
|
+
const latency = Date.now() - start;
|
|
2145
|
+
api.sendMessage(`Latency: ${latency}ms`, event.threadID);
|
|
2146
|
+
}
|
|
2147
|
+
});
|
|
2148
|
+
}
|
|
2149
|
+
},
|
|
2150
|
+
|
|
2151
|
+
userinfo: {
|
|
2152
|
+
description: "Get user information",
|
|
2153
|
+
execute: (api, event) => {
|
|
2154
|
+
api.getUserInfo(event.senderID, (err, userInfo) => {
|
|
2155
|
+
if (err) return api.sendMessage("Error getting user info!", event.threadID);
|
|
2156
|
+
|
|
2157
|
+
const user = userInfo[event.senderID];
|
|
2158
|
+
const info = `
|
|
2159
|
+
👤 USER INFO
|
|
2160
|
+
━━━━━━━━━━━━
|
|
2161
|
+
Name: ${user.name}
|
|
2162
|
+
Gender: ${user.gender}
|
|
2163
|
+
Profile: ${user.profileUrl}
|
|
2164
|
+
`.trim();
|
|
2165
|
+
|
|
2166
|
+
api.sendMessage(info, event.threadID);
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2169
|
+
},
|
|
2170
|
+
|
|
2171
|
+
time: {
|
|
2172
|
+
description: "Get current time",
|
|
2173
|
+
execute: (api, event) => {
|
|
2174
|
+
const now = new Date();
|
|
2175
|
+
api.sendMessage(`🕐 Current time: ${now.toLocaleString()}`, event.threadID);
|
|
2176
|
+
}
|
|
2177
|
+
},
|
|
2178
|
+
|
|
2179
|
+
help: {
|
|
2180
|
+
description: "Show command list",
|
|
2181
|
+
execute: (api, event) => {
|
|
2182
|
+
let helpText = "📋 AVAILABLE COMMANDS\n━━━━━━━━━━━━━━━\n";
|
|
2183
|
+
|
|
2184
|
+
for (let cmd in commands) {
|
|
2185
|
+
helpText += `${PREFIX}${cmd} - ${commands[cmd].description}\n`;
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
api.sendMessage(helpText, event.threadID);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
};
|
|
2192
|
+
|
|
2193
|
+
login(
|
|
2194
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
|
2195
|
+
(err, api) => {
|
|
2196
|
+
if (err) return console.error(err);
|
|
2197
|
+
|
|
2198
|
+
console.log("✅ Command handler bot started!");
|
|
2199
|
+
|
|
2200
|
+
api.setOptions({ listenEvents: true, selfListen: false });
|
|
2201
|
+
|
|
2202
|
+
api.listenMqtt((err, event) => {
|
|
2203
|
+
if (err) return console.error(err);
|
|
2204
|
+
|
|
2205
|
+
if (event.type === "message" && event.body) {
|
|
2206
|
+
const { body, threadID } = event;
|
|
2207
|
+
|
|
2208
|
+
// Check if message starts with prefix
|
|
2209
|
+
if (!body.startsWith(PREFIX)) return;
|
|
2210
|
+
|
|
2211
|
+
// Parse command
|
|
2212
|
+
const args = body.slice(PREFIX.length).trim().split(/ +/);
|
|
2213
|
+
const commandName = args.shift().toLowerCase();
|
|
2214
|
+
|
|
2215
|
+
// Execute command
|
|
2216
|
+
if (commands[commandName]) {
|
|
2217
|
+
try {
|
|
2218
|
+
commands[commandName].execute(api, event, args);
|
|
2219
|
+
} catch (error) {
|
|
2220
|
+
console.error("Command execution error:", error);
|
|
2221
|
+
api.sendMessage("Error executing command!", threadID);
|
|
2222
|
+
}
|
|
2223
|
+
} else {
|
|
2224
|
+
api.sendMessage(`Unknown command: ${commandName}\nUse ${PREFIX}help for command list`, threadID);
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
});
|
|
2228
|
+
}
|
|
2229
|
+
);
|
|
2230
|
+
```
|
|
2231
|
+
|
|
2232
|
+
---
|
|
2233
|
+
|
|
2234
|
+
## 5. ERROR HANDLING & BEST PRACTICES
|
|
2235
|
+
|
|
2236
|
+
### 5.1. Handle Checkpoint/Security Check
|
|
2237
|
+
|
|
2238
|
+
When Facebook detects unusual activity, account may be checkpointed:
|
|
2239
|
+
|
|
2240
|
+
```javascript
|
|
2241
|
+
login(credentials, (err, api) => {
|
|
2242
|
+
if (err) {
|
|
2243
|
+
switch (err.error) {
|
|
2244
|
+
case "login-approval":
|
|
2245
|
+
console.log("❗ 2FA code required");
|
|
2246
|
+
// Handle 2FA
|
|
2247
|
+
break;
|
|
2248
|
+
|
|
2249
|
+
case "checkpoint":
|
|
2250
|
+
console.log("❌ Account checkpointed!");
|
|
2251
|
+
console.log("Please login via browser and verify");
|
|
2252
|
+
break;
|
|
2253
|
+
|
|
2254
|
+
default:
|
|
2255
|
+
console.error("Login error:", err);
|
|
2256
|
+
}
|
|
2257
|
+
return;
|
|
2258
|
+
}
|
|
2259
|
+
});
|
|
2260
|
+
```
|
|
2261
|
+
|
|
2262
|
+
---
|
|
2263
|
+
|
|
2264
|
+
### 5.2. Auto-save AppState
|
|
2265
|
+
|
|
2266
|
+
```javascript
|
|
2267
|
+
// Save AppState every 10 minutes
|
|
2268
|
+
setInterval(() => {
|
|
2269
|
+
try {
|
|
2270
|
+
const appState = api.getAppState();
|
|
2271
|
+
fs.writeFileSync("appstate.json", JSON.stringify(appState, null, 2));
|
|
2272
|
+
console.log("🔄 AppState updated");
|
|
2273
|
+
} catch (error) {
|
|
2274
|
+
console.error("Error saving AppState:", error);
|
|
2275
|
+
}
|
|
2276
|
+
}, 10 * 60 * 1000);
|
|
2277
|
+
```
|
|
2278
|
+
|
|
2279
|
+
---
|
|
2280
|
+
|
|
2281
|
+
### 5.3. Connection Error Handling
|
|
2282
|
+
|
|
2283
|
+
```javascript
|
|
2284
|
+
api.listenMqtt((err, event) => {
|
|
2285
|
+
if (err) {
|
|
2286
|
+
console.error("Listen error:", err);
|
|
2287
|
+
|
|
2288
|
+
// Retry connection after 5 seconds
|
|
2289
|
+
setTimeout(() => {
|
|
2290
|
+
console.log("🔄 Reconnecting...");
|
|
2291
|
+
api.listenMqtt(arguments.callee);
|
|
2292
|
+
}, 5000);
|
|
2293
|
+
return;
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
// Handle events normally
|
|
2297
|
+
});
|
|
2298
|
+
```
|
|
2299
|
+
|
|
2300
|
+
---
|
|
2301
|
+
|
|
2302
|
+
### 5.4. Rate Limiting (Avoid Spam)
|
|
2303
|
+
|
|
2304
|
+
```javascript
|
|
2305
|
+
const MESSAGE_COOLDOWN = {}; // Store last message time
|
|
2306
|
+
|
|
2307
|
+
function canSendMessage(threadID, cooldownTime = 1000) {
|
|
2308
|
+
const now = Date.now();
|
|
2309
|
+
const lastTime = MESSAGE_COOLDOWN[threadID] || 0;
|
|
2310
|
+
|
|
2311
|
+
if (now - lastTime < cooldownTime) {
|
|
2312
|
+
return false;
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
MESSAGE_COOLDOWN[threadID] = now;
|
|
2316
|
+
return true;
|
|
2317
|
+
}
|
|
2318
|
+
|
|
2319
|
+
api.listenMqtt((err, event) => {
|
|
2320
|
+
if (err) return console.error(err);
|
|
2321
|
+
|
|
2322
|
+
if (event.type === "message") {
|
|
2323
|
+
// Check cooldown
|
|
2324
|
+
if (!canSendMessage(event.threadID, 2000)) {
|
|
2325
|
+
console.log("⏱️ On cooldown...");
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2329
|
+
// Handle message
|
|
2330
|
+
api.sendMessage("Response", event.threadID);
|
|
2331
|
+
}
|
|
2332
|
+
});
|
|
2333
|
+
```
|
|
2334
|
+
|
|
2335
|
+
---
|
|
2336
|
+
|
|
2337
|
+
### 5.5. Logging and Debug
|
|
2338
|
+
|
|
2339
|
+
```javascript
|
|
2340
|
+
// Enable detailed logging
|
|
2341
|
+
api.setOptions({
|
|
2342
|
+
logLevel: "verbose" // silent/error/warn/info/verbose
|
|
2343
|
+
});
|
|
2344
|
+
|
|
2345
|
+
// Custom logger
|
|
2346
|
+
function log(type, message, data = {}) {
|
|
2347
|
+
const timestamp = new Date().toISOString();
|
|
2348
|
+
console.log(`[${timestamp}] [${type.toUpperCase()}] ${message}`, data);
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
api.listenMqtt((err, event) => {
|
|
2352
|
+
if (err) {
|
|
2353
|
+
log("error", "Listen error", err);
|
|
2354
|
+
return;
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
log("info", "New event", {
|
|
2358
|
+
type: event.type,
|
|
2359
|
+
threadID: event.threadID
|
|
2360
|
+
});
|
|
2361
|
+
});
|
|
2362
|
+
```
|
|
2363
|
+
|
|
2364
|
+
---
|
|
2365
|
+
|
|
2366
|
+
### 5.6. Environment Variables for Credentials
|
|
2367
|
+
|
|
2368
|
+
```javascript
|
|
2369
|
+
require('dotenv').config();
|
|
2370
|
+
|
|
2371
|
+
const credentials = {
|
|
2372
|
+
email: process.env.FB_EMAIL,
|
|
2373
|
+
password: process.env.FB_PASSWORD
|
|
2374
|
+
};
|
|
2375
|
+
|
|
2376
|
+
// Or use AppState
|
|
2377
|
+
const credentials = {
|
|
2378
|
+
appState: JSON.parse(fs.readFileSync(process.env.APPSTATE_PATH, "utf8"))
|
|
2379
|
+
};
|
|
2380
|
+
```
|
|
2381
|
+
|
|
2382
|
+
**.env file:**
|
|
2383
|
+
```
|
|
2384
|
+
FB_EMAIL=your_email@example.com
|
|
2385
|
+
FB_PASSWORD=your_password
|
|
2386
|
+
APPSTATE_PATH=./appstate.json
|
|
2387
|
+
```
|
|
2388
|
+
|
|
2389
|
+
---
|
|
2390
|
+
|
|
2391
|
+
## 6. IMPORTANT NOTES
|
|
2392
|
+
|
|
2393
|
+
### ⚠️ Security Warnings
|
|
2394
|
+
|
|
2395
|
+
1. **Never share AppState**: The `appstate.json` file contains login information, never make it public
|
|
2396
|
+
2. **Use .gitignore**: Add `appstate.json` to `.gitignore`
|
|
2397
|
+
3. **Avoid hardcoding passwords**: Use environment variables or config files
|
|
2398
|
+
4. **Keep dependencies updated**: Regularly update the package
|
|
2399
|
+
|
|
2400
|
+
### 📝 Best Practices
|
|
2401
|
+
|
|
2402
|
+
1. **Use AppState instead of email/password**: Reduces checkpoint risk
|
|
2403
|
+
2. **Don't spam**: Avoid sending too many messages in short time
|
|
2404
|
+
3. **Complete error handling**: Always have callbacks to handle errors
|
|
2405
|
+
4. **Rate limiting**: Limit number of messages/requests
|
|
2406
|
+
5. **Log activities**: Keep logs for debugging
|
|
2407
|
+
|
|
2408
|
+
### 🚫 Avoid Getting Banned
|
|
2409
|
+
|
|
2410
|
+
- Don't login/logout repeatedly
|
|
2411
|
+
- Don't mass message strangers
|
|
2412
|
+
- Don't send spam links
|
|
2413
|
+
- Use real browser User-Agent
|
|
2414
|
+
- Limit requests per minute
|
|
2415
|
+
- Be a responsible Facebook citizen
|
|
2416
|
+
|
|
2417
|
+
---
|
|
2418
|
+
|
|
2419
|
+
## 7. TROUBLESHOOTING
|
|
2420
|
+
|
|
2421
|
+
### Error: "Wrong username/password"
|
|
2422
|
+
- Check email and password
|
|
2423
|
+
- Try logging in manually via browser
|
|
2424
|
+
- Account may be checkpointed
|
|
2425
|
+
|
|
2426
|
+
### Error: "Login approval needed"
|
|
2427
|
+
- Account has 2FA enabled
|
|
2428
|
+
- Provide 2FA verification code
|
|
2429
|
+
|
|
2430
|
+
### Error: "Checkpoint required"
|
|
2431
|
+
- Login to Facebook via browser
|
|
2432
|
+
- Complete verification steps
|
|
2433
|
+
- Get new AppState after verification
|
|
2434
|
+
|
|
2435
|
+
### Bot not receiving messages
|
|
2436
|
+
- Check internet connection
|
|
2437
|
+
- Check logs for detailed errors
|
|
2438
|
+
- Try restarting bot
|
|
2439
|
+
- Update AppState
|
|
2440
|
+
|
|
2441
|
+
### Messages sending too slowly
|
|
2442
|
+
- Implement message queue
|
|
2443
|
+
- Use rate limiting
|
|
2444
|
+
- Check network latency
|
|
2445
|
+
|
|
2446
|
+
---
|
|
2447
|
+
|
|
2448
|
+
## 8. ADVANCED FEATURES
|
|
2449
|
+
|
|
2450
|
+
### 8.1. Message Queue System
|
|
2451
|
+
|
|
2452
|
+
```javascript
|
|
2453
|
+
class MessageQueue {
|
|
2454
|
+
constructor(api) {
|
|
2455
|
+
this.api = api;
|
|
2456
|
+
this.queue = [];
|
|
2457
|
+
this.processing = false;
|
|
2458
|
+
this.delay = 1000; // 1 second delay between messages
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
add(message, threadID, messageID) {
|
|
2462
|
+
this.queue.push({ message, threadID, messageID });
|
|
2463
|
+
if (!this.processing) {
|
|
2464
|
+
this.process();
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
async process() {
|
|
2469
|
+
this.processing = true;
|
|
2470
|
+
|
|
2471
|
+
while (this.queue.length > 0) {
|
|
2472
|
+
const { message, threadID, messageID } = this.queue.shift();
|
|
2473
|
+
|
|
2474
|
+
await new Promise((resolve) => {
|
|
2475
|
+
this.api.sendMessage(message, threadID, messageID, (err) => {
|
|
2476
|
+
if (err) console.error("Send error:", err);
|
|
2477
|
+
setTimeout(resolve, this.delay);
|
|
2478
|
+
});
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
this.processing = false;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
// Usage
|
|
2487
|
+
const messageQueue = new MessageQueue(api);
|
|
2488
|
+
|
|
2489
|
+
api.listenMqtt((err, event) => {
|
|
2490
|
+
if (err) return console.error(err);
|
|
2491
|
+
|
|
2492
|
+
if (event.type === "message") {
|
|
2493
|
+
messageQueue.add("Response", event.threadID, event.messageID);
|
|
2494
|
+
}
|
|
2495
|
+
});
|
|
2496
|
+
```
|
|
2497
|
+
|
|
2498
|
+
---
|
|
2499
|
+
|
|
2500
|
+
### 8.2. Multi-Account Bot Manager
|
|
2501
|
+
|
|
2502
|
+
```javascript
|
|
2503
|
+
const fs = require("fs");
|
|
2504
|
+
const login = require("surya-sahil-fca");
|
|
2505
|
+
|
|
2506
|
+
class BotManager {
|
|
2507
|
+
constructor() {
|
|
2508
|
+
this.bots = new Map();
|
|
2509
|
+
}
|
|
2510
|
+
|
|
2511
|
+
async addBot(name, appStatePath) {
|
|
2512
|
+
return new Promise((resolve, reject) => {
|
|
2513
|
+
const credentials = {
|
|
2514
|
+
appState: JSON.parse(fs.readFileSync(appStatePath, "utf8"))
|
|
2515
|
+
};
|
|
2516
|
+
|
|
2517
|
+
login(credentials, (err, api) => {
|
|
2518
|
+
if (err) {
|
|
2519
|
+
reject(err);
|
|
2520
|
+
return;
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
this.bots.set(name, api);
|
|
2524
|
+
console.log(`✅ Bot "${name}" connected`);
|
|
2525
|
+
resolve(api);
|
|
2526
|
+
});
|
|
2527
|
+
});
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
getBot(name) {
|
|
2531
|
+
return this.bots.get(name);
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
getAllBots() {
|
|
2535
|
+
return Array.from(this.bots.values());
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
// Usage
|
|
2540
|
+
const manager = new BotManager();
|
|
2541
|
+
|
|
2542
|
+
(async () => {
|
|
2543
|
+
await manager.addBot("bot1", "./appstate1.json");
|
|
2544
|
+
await manager.addBot("bot2", "./appstate2.json");
|
|
2545
|
+
|
|
2546
|
+
const bot1 = manager.getBot("bot1");
|
|
2547
|
+
const bot2 = manager.getBot("bot2");
|
|
2548
|
+
|
|
2549
|
+
// Use bots independently
|
|
2550
|
+
bot1.sendMessage("Message from Bot 1", threadID);
|
|
2551
|
+
bot2.sendMessage("Message from Bot 2", threadID);
|
|
2552
|
+
})();
|
|
2553
|
+
```
|
|
2554
|
+
|
|
2555
|
+
---
|
|
2556
|
+
|
|
2557
|
+
### 8.3. Database Integration (SQLite Example)
|
|
2558
|
+
|
|
2559
|
+
```javascript
|
|
2560
|
+
const sqlite3 = require('sqlite3').verbose();
|
|
2561
|
+
const db = new sqlite3.Database('./bot.db');
|
|
2562
|
+
|
|
2563
|
+
// Initialize database
|
|
2564
|
+
db.serialize(() => {
|
|
2565
|
+
db.run(`CREATE TABLE IF NOT EXISTS users (
|
|
2566
|
+
user_id TEXT PRIMARY KEY,
|
|
2567
|
+
username TEXT,
|
|
2568
|
+
message_count INTEGER DEFAULT 0,
|
|
2569
|
+
last_interaction TEXT
|
|
2570
|
+
)`);
|
|
2571
|
+
});
|
|
2572
|
+
|
|
2573
|
+
// Track user messages
|
|
2574
|
+
function trackUser(userID, username) {
|
|
2575
|
+
db.run(`
|
|
2576
|
+
INSERT INTO users (user_id, username, message_count, last_interaction)
|
|
2577
|
+
VALUES (?, ?, 1, datetime('now'))
|
|
2578
|
+
ON CONFLICT(user_id) DO UPDATE SET
|
|
2579
|
+
message_count = message_count + 1,
|
|
2580
|
+
last_interaction = datetime('now')
|
|
2581
|
+
`, [userID, username]);
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
// Get user stats
|
|
2585
|
+
function getUserStats(userID, callback) {
|
|
2586
|
+
db.get('SELECT * FROM users WHERE user_id = ?', [userID], callback);
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2589
|
+
// Usage in bot
|
|
2590
|
+
api.listenMqtt((err, event) => {
|
|
2591
|
+
if (err) return console.error(err);
|
|
2592
|
+
|
|
2593
|
+
if (event.type === "message") {
|
|
2594
|
+
// Track user
|
|
2595
|
+
api.getUserInfo(event.senderID, (err, info) => {
|
|
2596
|
+
if (!err) {
|
|
2597
|
+
const username = info[event.senderID].name;
|
|
2598
|
+
trackUser(event.senderID, username);
|
|
2599
|
+
}
|
|
2600
|
+
});
|
|
2601
|
+
|
|
2602
|
+
// Stats command
|
|
2603
|
+
if (event.body === "/stats") {
|
|
2604
|
+
getUserStats(event.senderID, (err, row) => {
|
|
2605
|
+
if (err || !row) return;
|
|
2606
|
+
|
|
2607
|
+
const stats = `
|
|
2608
|
+
📊 YOUR STATS
|
|
2609
|
+
━━━━━━━━━━━━
|
|
2610
|
+
Messages: ${row.message_count}
|
|
2611
|
+
Last seen: ${row.last_interaction}
|
|
2612
|
+
`.trim();
|
|
2613
|
+
|
|
2614
|
+
api.sendMessage(stats, event.threadID);
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
});
|
|
2619
|
+
```
|
|
2620
|
+
|
|
2621
|
+
---
|
|
2622
|
+
|
|
2623
|
+
## 9. RESOURCES
|
|
2624
|
+
|
|
2625
|
+
- **GitHub Repository**: https://github.com/surya-sahil/fca-unofficial
|
|
2626
|
+
- **NPM Package**: surya-sahil-fca
|
|
2627
|
+
- **AppState Tool**: https://github.com/c3cbot/c3c-fbstate
|
|
2628
|
+
- **Facebook Developer Docs**: https://developers.facebook.com/docs/messenger-platform
|
|
2629
|
+
|
|
2630
|
+
---
|
|
2631
|
+
|
|
2632
|
+
## Conclusion
|
|
2633
|
+
|
|
2634
|
+
This is a comprehensive documentation for **surya-sahil-fca** API methods. This library is very powerful but should be used carefully to avoid violating Facebook's policies and getting your account banned.
|
|
2635
|
+
|
|
2636
|
+
**Happy bot coding! 🚀**
|