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/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! 🚀**