@dongdev/fca-unofficial 2.0.8 → 2.0.11
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 +1699 -1434
- package/README.md +250 -168
- package/package.json +53 -27
- package/src/api/socket/listenMqtt.js +1 -1
- package/CHANGELOG.md +0 -55
- package/LICENSE-MIT +0 -21
- package/func/checkUpdate.js +0 -58
- package/func/logger.js +0 -48
- package/func/login.js +0 -0
- package/index.d.ts +0 -618
- package/module/config.js +0 -34
- package/module/login.js +0 -47
- package/module/loginHelper.js +0 -635
- package/module/options.js +0 -45
package/DOCS.md
CHANGED
@@ -1,1873 +1,2138 @@
|
|
1
|
-
# Documentation
|
2
|
-
|
3
|
-
- [`login`](#login)
|
4
|
-
- [`api.addUserToGroup`](#addUserToGroup)
|
5
|
-
- [`api.changeAdminStatus`](#changeAdminStatus)
|
6
|
-
- [`api.changeArchivedStatus`](#changeArchivedStatus)
|
7
|
-
- [`api.changeBlockedStatus`](#changeBlockedStatus)
|
8
|
-
- [`api.changeGroupImage`](#changeGroupImage)
|
9
|
-
- [`api.changeNickname`](#changeNickname)
|
10
|
-
- [`api.changeThreadColor`](#changeThreadColor)
|
11
|
-
- [`api.changeThreadEmoji`](#changeThreadEmoji)
|
12
|
-
- [`api.createNewGroup`](#createNewGroup)
|
13
|
-
- [`api.createPoll`](#createPoll)
|
14
|
-
- [`api.deleteMessage`](#deleteMessage)
|
15
|
-
- [`api.deleteThread`](#deleteThread)
|
16
|
-
- [`api.forwardAttachment`](#forwardAttachment)
|
17
|
-
- [`api.getAppState`](#getAppState)
|
18
|
-
- [`api.getCurrentUserID`](#getCurrentUserID)
|
19
|
-
- [`api.getEmojiUrl`](#getEmojiUrl)
|
20
|
-
- [`api.getFriendsList`](#getFriendsList)
|
21
|
-
- [`api.getThreadHistory`](#getThreadHistory)
|
22
|
-
- [`api.getThreadInfo`](#getThreadInfo)
|
23
|
-
- [`api.getThreadList`](#getThreadList)
|
24
|
-
- [`api.getThreadPictures`](#getThreadPictures)
|
25
|
-
- [`api.getUserID`](#getUserID)
|
26
|
-
- [`api.getUserInfo`](#getUserInfo)
|
27
|
-
- [`api.handleMessageRequest`](#handleMessageRequest)
|
28
|
-
- [`api.listenMqtt`](#listenMqtt)
|
29
|
-
- [`api.logout`](#logout)
|
30
|
-
- [`api.markAsDelivered`](#markAsDelivered)
|
31
|
-
- [`api.markAsRead`](#markAsRead)
|
32
|
-
- [`api.markAsReadAll`](#markAsReadAll)
|
33
|
-
- [`api.markAsSeen`](#markAsSeen)
|
34
|
-
- [`api.muteThread`](#muteThread)
|
35
|
-
- [`api.removeUserFromGroup`](#removeUserFromGroup)
|
36
|
-
- [`api.resolvePhotoUrl`](#resolvePhotoUrl)
|
37
|
-
- [`api.searchForThread`](#searchForThread)
|
38
|
-
- [`api.sendMessage`](#sendMessage)
|
39
|
-
- [`api.sendTypingIndicator`](#sendTypingIndicator)
|
40
|
-
- [`api.setMessageReaction`](#setMessageReaction)
|
41
|
-
- [`api.setOptions`](#setOptions)
|
42
|
-
- [`api.setTitle`](#setTitle)
|
43
|
-
- [`api.threadColors`](#threadColors)
|
44
|
-
- [`api.unsendMessage`](#unsendMessage)
|
1
|
+
# FCA-Unofficial - Complete API Documentation
|
45
2
|
|
46
|
-
|
47
|
-
|
48
|
-
### Password safety
|
49
|
-
|
50
|
-
**Read this** before you _copy+paste_ examples from below.
|
51
|
-
|
52
|
-
You should not store Facebook password in your scripts.
|
53
|
-
There are few good reasons:
|
3
|
+
## Introduction
|
54
4
|
|
55
|
-
-
|
56
|
-
- Backups of source files may be readable by someone else. "_There is nothing secret in my code, why should I ever password protect my backups_"
|
57
|
-
- You can't push your code to Github (or any onther service) without removing your password from the file. Remember: Even if you undo your accidential commit with password, Git doesn't delete it, that commit is just not used but is still readable by everybody.
|
58
|
-
- If you change your password in the future (maybe it leaked because _someone_ stored password in source file… oh… well…) you will have to change every occurrence in your scripts
|
5
|
+
**@dongdev/fca-unofficial** 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.
|
59
6
|
|
60
|
-
|
61
|
-
This way you can put password in your code for a minute, login to facebook and then remove it.
|
62
|
-
|
63
|
-
If you want to be even more safe: _login.js_ can get password with `require("readline")` or with environment variables like this:
|
64
|
-
|
65
|
-
```js
|
66
|
-
var credentials = {
|
67
|
-
email: process.env.FB_EMAIL,
|
68
|
-
password: process.env.FB_PASSWORD
|
69
|
-
};
|
70
|
-
```
|
7
|
+
## Installation
|
71
8
|
|
72
9
|
```bash
|
73
|
-
|
74
|
-
FB_PASSWORD="MySuperHardP@ssw0rd"
|
75
|
-
nodejs login.js
|
10
|
+
npm install @dongdev/fca-unofficial@latest
|
76
11
|
```
|
77
12
|
|
78
13
|
---
|
79
14
|
|
80
|
-
|
15
|
+
## 1. LOGIN
|
81
16
|
|
82
|
-
###
|
17
|
+
### 1.1. Login with Email & Password
|
83
18
|
|
84
|
-
|
19
|
+
```javascript
|
20
|
+
const login = require("@dongdev/fca-unofficial");
|
85
21
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
If `callback` is supplied:
|
91
|
-
|
92
|
-
- `callback` will be called with a `null` object (for potential errors) and with an object containing all the available functions if logged in successfully.
|
93
|
-
|
94
|
-
- `callback` will be called with an error object if failed to login.
|
22
|
+
const credentials = {
|
23
|
+
email: "your_email@example.com",
|
24
|
+
password: "your_password"
|
25
|
+
};
|
95
26
|
|
96
|
-
|
27
|
+
login(credentials, (err, api) => {
|
28
|
+
if (err) {
|
29
|
+
console.error("Login error:", err);
|
30
|
+
return;
|
31
|
+
}
|
32
|
+
console.log("Login successful!");
|
33
|
+
});
|
34
|
+
```
|
97
35
|
|
98
|
-
|
36
|
+
### 1.2. Login with 2FA (Two-Factor Authentication)
|
99
37
|
|
100
|
-
|
38
|
+
When your account has 2FA enabled, you need to provide the 2FA code:
|
101
39
|
|
102
|
-
|
40
|
+
```javascript
|
41
|
+
const login = require("@dongdev/fca-unofficial");
|
42
|
+
const readline = require("readline");
|
103
43
|
|
104
|
-
|
105
|
-
|
106
|
-
|
44
|
+
const rl = readline.createInterface({
|
45
|
+
input: process.stdin,
|
46
|
+
output: process.stdout
|
47
|
+
});
|
107
48
|
|
108
|
-
|
49
|
+
const credentials = {
|
50
|
+
email: "your_email@example.com",
|
51
|
+
password: "your_password"
|
52
|
+
};
|
109
53
|
|
110
|
-
|
111
|
-
|
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
|
+
}
|
112
69
|
|
113
|
-
|
114
|
-
if (err) return console.error(err);
|
115
|
-
// Here you can use the api
|
70
|
+
console.log("Login successful!");
|
116
71
|
});
|
117
72
|
```
|
118
73
|
|
119
|
-
|
74
|
+
### 1.3. Login with AppState (Recommended)
|
120
75
|
|
121
|
-
|
122
|
-
const fs = require("fs");
|
123
|
-
const login = require("fca-unofficial");
|
76
|
+
AppState is saved cookies and session data. Login with AppState helps avoid entering password each time and reduces checkpoint risk.
|
124
77
|
|
125
|
-
|
126
|
-
if (err) return console.error(err);
|
78
|
+
#### Get and Save AppState:
|
127
79
|
|
128
|
-
|
129
|
-
|
130
|
-
|
80
|
+
```javascript
|
81
|
+
const fs = require("fs");
|
82
|
+
const login = require("@dongdev/fca-unofficial");
|
131
83
|
|
132
|
-
|
84
|
+
const credentials = {
|
85
|
+
email: "your_email@example.com",
|
86
|
+
password: "your_password"
|
87
|
+
};
|
133
88
|
|
134
|
-
|
135
|
-
|
136
|
-
|
89
|
+
login(credentials, (err, api) => {
|
90
|
+
if (err) {
|
91
|
+
console.error("Login error:", err);
|
92
|
+
return;
|
93
|
+
}
|
137
94
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
);
|
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
|
+
});
|
145
104
|
```
|
146
105
|
|
147
|
-
|
148
|
-
|
149
|
-
**Example**:
|
106
|
+
#### Use Saved AppState:
|
150
107
|
|
151
|
-
```
|
108
|
+
```javascript
|
152
109
|
const fs = require("fs");
|
153
|
-
const login = require("fca-unofficial");
|
154
|
-
const readline = require("readline");
|
110
|
+
const login = require("@dongdev/fca-unofficial");
|
155
111
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
});
|
112
|
+
const credentials = {
|
113
|
+
appState: JSON.parse(fs.readFileSync("appstate.json", "utf8"))
|
114
|
+
};
|
160
115
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
case "login-approval":
|
166
|
-
console.log("Enter code > ");
|
167
|
-
rl.on("line", line => {
|
168
|
-
err.continue(line);
|
169
|
-
rl.close();
|
170
|
-
});
|
171
|
-
break;
|
172
|
-
default:
|
173
|
-
console.error(err);
|
116
|
+
login(credentials, (err, api) => {
|
117
|
+
if (err) {
|
118
|
+
console.error("Login error:", err);
|
119
|
+
return;
|
174
120
|
}
|
175
|
-
return;
|
176
|
-
}
|
177
121
|
|
178
|
-
|
122
|
+
console.log("Login successful with AppState!");
|
179
123
|
});
|
180
124
|
```
|
181
125
|
|
182
|
-
**
|
126
|
+
**Note:** You can use [c3c-fbstate](https://github.com/c3cbot/c3c-fbstate) tool to get AppState from browser.
|
183
127
|
|
184
128
|
---
|
185
129
|
|
186
|
-
|
187
|
-
|
188
|
-
### api.addUserToGroup(userID, threadID[, callback])
|
130
|
+
## 2. CONFIGURATION (Options)
|
189
131
|
|
190
|
-
|
132
|
+
After login, you can configure API options:
|
191
133
|
|
192
|
-
|
134
|
+
```javascript
|
135
|
+
api.setOptions({
|
136
|
+
// Listen to events (add/remove members, change group name, etc.)
|
137
|
+
listenEvents: true,
|
193
138
|
|
194
|
-
|
195
|
-
|
196
|
-
- `callback(err)`: A callback called when the query is done (either with an error or with no arguments).
|
139
|
+
// Listen to your own messages
|
140
|
+
selfListen: false,
|
197
141
|
|
198
|
-
|
199
|
-
|
200
|
-
<a name="changeAdminStatus"></a>
|
142
|
+
// Auto mark messages as read
|
143
|
+
autoMarkRead: false,
|
201
144
|
|
202
|
-
|
145
|
+
// Auto mark as delivered
|
146
|
+
autoMarkDelivery: false,
|
203
147
|
|
204
|
-
|
148
|
+
// Online status (true/false)
|
149
|
+
online: true,
|
205
150
|
|
206
|
-
|
151
|
+
// Log level (silent/error/warn/info/verbose)
|
152
|
+
logLevel: "info",
|
207
153
|
|
208
|
-
|
209
|
-
|
210
|
-
|
154
|
+
// Custom user agent
|
155
|
+
userAgent: "Mozilla/5.0..."
|
156
|
+
});
|
157
|
+
```
|
211
158
|
|
212
|
-
|
159
|
+
---
|
213
160
|
|
214
|
-
|
215
|
-
const fs = require("fs");
|
216
|
-
const login = require("fca-unofficial");
|
161
|
+
## 3. DETAILED API METHODS
|
217
162
|
|
218
|
-
|
219
|
-
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
220
|
-
async function(err, api) {
|
221
|
-
if (err) return console.error(err);
|
163
|
+
### 3.1. sendMessage - Send Message
|
222
164
|
|
223
|
-
|
224
|
-
let newAdmins = ["111111111111111", "222222222222222"];
|
225
|
-
await api.changeAdminStatus(threadID, newAdmins, true);
|
165
|
+
Send message to user or group chat.
|
226
166
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
);
|
167
|
+
#### Syntax:
|
168
|
+
```javascript
|
169
|
+
api.sendMessage(message, threadID, [messageID], [callback])
|
231
170
|
```
|
232
171
|
|
233
|
-
|
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)`
|
234
177
|
|
235
|
-
|
178
|
+
#### Basic Example:
|
236
179
|
|
237
|
-
|
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
|
+
```
|
238
189
|
|
239
|
-
|
190
|
+
#### Send Messages with Various Content Types:
|
240
191
|
|
241
|
-
|
192
|
+
```javascript
|
193
|
+
// 1. Simple text message
|
194
|
+
api.sendMessage("Hello World", threadID);
|
242
195
|
|
243
|
-
|
244
|
-
|
245
|
-
|
196
|
+
// 2. Send sticker
|
197
|
+
api.sendMessage({
|
198
|
+
sticker: "767334476655547" // Sticker ID
|
199
|
+
}, threadID);
|
246
200
|
|
247
|
-
|
201
|
+
// 3. Send emoji with size
|
202
|
+
api.sendMessage({
|
203
|
+
body: "Awesome!",
|
204
|
+
emoji: "👍",
|
205
|
+
emojiSize: "large" // small, medium, large
|
206
|
+
}, threadID);
|
248
207
|
|
249
|
-
|
208
|
+
// 4. Send file/image
|
250
209
|
const fs = require("fs");
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
)
|
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);
|
263
252
|
```
|
264
253
|
|
265
254
|
---
|
266
255
|
|
267
|
-
|
268
|
-
|
269
|
-
### api.changeBlockedStatus(userID, block[, callback])
|
256
|
+
### 3.2. listenMqtt - Listen for Messages
|
270
257
|
|
271
|
-
|
258
|
+
Listen for messages and events from Facebook Messenger (using MQTT).
|
272
259
|
|
273
|
-
|
260
|
+
#### Syntax:
|
261
|
+
```javascript
|
262
|
+
const stopListening = api.listenMqtt(callback);
|
263
|
+
```
|
274
264
|
|
275
|
-
|
276
|
-
- `
|
277
|
-
- `callback(err)`: A callback called when the query is done (either with an error or with no arguments).
|
265
|
+
#### Parameters:
|
266
|
+
- `callback`: Function `(err, event)` called when new message/event arrives
|
278
267
|
|
279
|
-
|
268
|
+
#### Example:
|
280
269
|
|
281
|
-
|
270
|
+
```javascript
|
271
|
+
const stopListening = api.listenMqtt((err, event) => {
|
272
|
+
if (err) {
|
273
|
+
console.error("Listen error:", err);
|
274
|
+
return;
|
275
|
+
}
|
282
276
|
|
283
|
-
|
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);
|
284
283
|
|
285
|
-
|
284
|
+
// Reply to message
|
285
|
+
if (event.body === "Hi") {
|
286
|
+
api.sendMessage("Hello!", event.threadID);
|
287
|
+
}
|
288
|
+
break;
|
286
289
|
|
287
|
-
|
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
|
+
});
|
288
309
|
|
289
|
-
|
290
|
-
|
291
|
-
|
310
|
+
// Stop listening
|
311
|
+
// stopListening();
|
312
|
+
```
|
292
313
|
|
293
|
-
|
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
|
+
attachments: [], // Array of attachments
|
325
|
+
mentions: {}, // Object of mentions
|
326
|
+
timestamp: 1234567890000,
|
327
|
+
isGroup: false // true if group chat
|
328
|
+
}
|
294
329
|
|
295
|
-
|
296
|
-
|
297
|
-
|
330
|
+
// Event type: "event"
|
331
|
+
{
|
332
|
+
type: "event",
|
333
|
+
threadID: "1234567890",
|
334
|
+
logMessageType: "log:subscribe",
|
335
|
+
logMessageData: {...},
|
336
|
+
author: "100012345678901"
|
337
|
+
}
|
298
338
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
339
|
+
// Event type: "typ" (typing)
|
340
|
+
{
|
341
|
+
type: "typ",
|
342
|
+
threadID: "1234567890",
|
343
|
+
from: "100012345678901",
|
344
|
+
isTyping: true
|
345
|
+
}
|
303
346
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
}
|
312
|
-
);
|
347
|
+
// Event type: "read_receipt" (read)
|
348
|
+
{
|
349
|
+
type: "read_receipt",
|
350
|
+
threadID: "1234567890",
|
351
|
+
reader: "100012345678901",
|
352
|
+
time: 1234567890000
|
353
|
+
}
|
313
354
|
```
|
314
355
|
|
315
356
|
---
|
316
357
|
|
317
|
-
|
358
|
+
### 3.3. getUserInfo - Get User Information
|
318
359
|
|
319
|
-
|
360
|
+
Get detailed information about one or more users.
|
320
361
|
|
321
|
-
|
322
|
-
|
323
|
-
|
362
|
+
#### Syntax:
|
363
|
+
```javascript
|
364
|
+
api.getUserInfo(userID, callback);
|
365
|
+
```
|
324
366
|
|
325
|
-
|
326
|
-
- `threadID`: String representing the ID of the thread.
|
327
|
-
- `participantID`: String representing the ID of the user.
|
328
|
-
- `callback(err)`: An optional callback called when the change is done (either with an error or null).
|
367
|
+
#### Example:
|
329
368
|
|
330
|
-
|
369
|
+
```javascript
|
370
|
+
// Get info for 1 user
|
371
|
+
api.getUserInfo("100012345678901", (err, userInfo) => {
|
372
|
+
if (err) {
|
373
|
+
console.error(err);
|
374
|
+
return;
|
375
|
+
}
|
331
376
|
|
332
|
-
|
333
|
-
|
334
|
-
|
377
|
+
console.log(userInfo);
|
378
|
+
// {
|
379
|
+
// "100012345678901": {
|
380
|
+
// name: "John Doe",
|
381
|
+
// firstName: "John",
|
382
|
+
// vanity: "john.doe",
|
383
|
+
// thumbSrc: "avatar_url",
|
384
|
+
// profileUrl: "https://facebook.com/john.doe",
|
385
|
+
// gender: "MALE", // MALE/FEMALE
|
386
|
+
// type: "user",
|
387
|
+
// isFriend: true,
|
388
|
+
// isBirthday: false
|
389
|
+
// }
|
390
|
+
// }
|
391
|
+
});
|
335
392
|
|
336
|
-
|
337
|
-
|
338
|
-
(err, api) => {
|
393
|
+
// Get info for multiple users
|
394
|
+
api.getUserInfo(["100012345678901", "100012345678902"], (err, userInfo) => {
|
339
395
|
if (err) return console.error(err);
|
340
396
|
|
341
|
-
|
342
|
-
|
343
|
-
}
|
344
|
-
|
345
|
-
);
|
397
|
+
for (let id in userInfo) {
|
398
|
+
console.log(userInfo[id].name);
|
399
|
+
}
|
400
|
+
});
|
346
401
|
```
|
347
402
|
|
348
403
|
---
|
349
404
|
|
350
|
-
|
351
|
-
|
352
|
-
### api.changeThreadColor(color, threadID[, callback])
|
353
|
-
|
354
|
-
Will change the thread color to the given hex string color ("#0000ff"). Set it
|
355
|
-
to empty string if you want the default.
|
356
|
-
|
357
|
-
Note: the color needs to start with a "#".
|
405
|
+
### 3.4. getThreadInfo - Get Thread Information
|
358
406
|
|
359
|
-
|
407
|
+
Get information about conversation/group chat.
|
360
408
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
**Example**
|
409
|
+
#### Syntax:
|
410
|
+
```javascript
|
411
|
+
api.getThreadInfo(threadID, callback);
|
412
|
+
```
|
366
413
|
|
367
|
-
|
368
|
-
const fs = require("fs");
|
369
|
-
const login = require("fca-unofficial");
|
414
|
+
#### Example:
|
370
415
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
416
|
+
```javascript
|
417
|
+
api.getThreadInfo("1234567890", (err, threadInfo) => {
|
418
|
+
if (err) {
|
419
|
+
console.error(err);
|
420
|
+
return;
|
421
|
+
}
|
375
422
|
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
);
|
423
|
+
console.log("Group name:", threadInfo.threadName);
|
424
|
+
console.log("Member count:", threadInfo.participantIDs.length);
|
425
|
+
console.log("Members list:", threadInfo.participantIDs);
|
426
|
+
console.log("Admins:", threadInfo.adminIDs);
|
427
|
+
console.log("Nicknames:", threadInfo.nicknames);
|
428
|
+
console.log("Chat color:", threadInfo.color);
|
429
|
+
console.log("Emoji:", threadInfo.emoji);
|
430
|
+
});
|
381
431
|
```
|
382
432
|
|
383
433
|
---
|
384
434
|
|
385
|
-
|
435
|
+
### 3.5. changeThreadColor - Change Chat Color
|
386
436
|
|
387
|
-
|
437
|
+
Change the color of conversation.
|
388
438
|
|
389
|
-
|
439
|
+
#### Syntax:
|
440
|
+
```javascript
|
441
|
+
api.changeThreadColor(color, threadID, callback);
|
442
|
+
```
|
390
443
|
|
391
|
-
|
444
|
+
#### Example:
|
445
|
+
|
446
|
+
```javascript
|
447
|
+
// Color can be:
|
448
|
+
// "#0084ff" (Messenger Blue)
|
449
|
+
// "#44bec7" (Teal Blue)
|
450
|
+
// "#ffc300" (Yellow)
|
451
|
+
// "#fa3c4c" (Red)
|
452
|
+
// "#d696bb" (Pink)
|
453
|
+
// "#6699cc" (Sky Blue)
|
454
|
+
// "#13cf13" (Green)
|
455
|
+
// "#ff7e29" (Orange)
|
456
|
+
// "#e68585" (Light Red)
|
457
|
+
// "#7646ff" (Purple)
|
458
|
+
// "#20cef5" (Cyan)
|
459
|
+
// or any hex color code
|
460
|
+
|
461
|
+
api.changeThreadColor("#ffc300", "1234567890", (err) => {
|
462
|
+
if (err) {
|
463
|
+
console.error("Change color error:", err);
|
464
|
+
return;
|
465
|
+
}
|
466
|
+
console.log("Chat color changed successfully!");
|
467
|
+
});
|
468
|
+
```
|
392
469
|
|
393
|
-
|
470
|
+
---
|
394
471
|
|
395
|
-
|
396
|
-
- `threadID`: String representing the ID of the thread.
|
397
|
-
- `callback(err)`: A callback called when the change is done (either with an error or null).
|
472
|
+
### 3.6. changeThreadEmoji - Change Group Emoji
|
398
473
|
|
399
|
-
|
474
|
+
Change the default emoji of conversation.
|
400
475
|
|
401
|
-
|
402
|
-
|
403
|
-
|
476
|
+
#### Syntax:
|
477
|
+
```javascript
|
478
|
+
api.changeThreadEmoji(emoji, threadID, callback);
|
479
|
+
```
|
404
480
|
|
405
|
-
|
406
|
-
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
407
|
-
(err, api) => {
|
408
|
-
if (err) return console.error(err);
|
481
|
+
#### Example:
|
409
482
|
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
483
|
+
```javascript
|
484
|
+
api.changeThreadEmoji("👍", "1234567890", (err) => {
|
485
|
+
if (err) {
|
486
|
+
console.error("Change emoji error:", err);
|
487
|
+
return;
|
488
|
+
}
|
489
|
+
console.log("Emoji changed successfully!");
|
490
|
+
});
|
415
491
|
```
|
416
492
|
|
417
493
|
---
|
418
494
|
|
419
|
-
|
495
|
+
### 3.7. setTitle - Change Group Name
|
420
496
|
|
421
|
-
|
497
|
+
Change the name of group chat.
|
422
498
|
|
423
|
-
|
499
|
+
#### Syntax:
|
500
|
+
```javascript
|
501
|
+
api.setTitle(newTitle, threadID, callback);
|
502
|
+
```
|
424
503
|
|
425
|
-
|
504
|
+
#### Example:
|
426
505
|
|
427
|
-
|
428
|
-
|
429
|
-
|
506
|
+
```javascript
|
507
|
+
api.setTitle("New Chat Group", "1234567890", (err) => {
|
508
|
+
if (err) {
|
509
|
+
console.error("Change name error:", err);
|
510
|
+
return;
|
511
|
+
}
|
512
|
+
console.log("Group name changed successfully!");
|
513
|
+
});
|
514
|
+
```
|
430
515
|
|
431
516
|
---
|
432
517
|
|
433
|
-
|
434
|
-
|
435
|
-
### api.createPoll(title, threadID[, options][, callback]) (_temporary deprecated because Facebook is updating this feature_)
|
518
|
+
### 3.8. addUserToGroup - Add Member to Group
|
436
519
|
|
437
|
-
|
520
|
+
Add user to group chat.
|
438
521
|
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
- `options`: An optional `string : bool` dictionary to specify initial poll options and their initial states (selected/not selected), respectively.
|
444
|
-
- `callback(err)`: An optional callback called when the poll is posted (either with an error or null) - can omit the `options` parameter and use this as the third parameter if desired.
|
522
|
+
#### Syntax:
|
523
|
+
```javascript
|
524
|
+
api.addUserToGroup(userID, threadID, callback);
|
525
|
+
```
|
445
526
|
|
446
|
-
|
527
|
+
#### Example:
|
447
528
|
|
448
|
-
```
|
449
|
-
|
450
|
-
|
529
|
+
```javascript
|
530
|
+
// Add 1 person
|
531
|
+
api.addUserToGroup("100012345678901", "1234567890", (err) => {
|
532
|
+
if (err) {
|
533
|
+
console.error("Add user error:", err);
|
534
|
+
return;
|
535
|
+
}
|
536
|
+
console.log("Member added successfully!");
|
537
|
+
});
|
451
538
|
|
452
|
-
|
453
|
-
|
454
|
-
(err, api) => {
|
539
|
+
// Add multiple people
|
540
|
+
api.addUserToGroup(["100012345678901", "100012345678902"], "1234567890", (err) => {
|
455
541
|
if (err) return console.error(err);
|
456
|
-
|
457
|
-
|
458
|
-
"Example Poll",
|
459
|
-
"000000000000000",
|
460
|
-
{
|
461
|
-
"Option 1": false,
|
462
|
-
"Option 2": true
|
463
|
-
},
|
464
|
-
err => {
|
465
|
-
if (err) return console.error(err);
|
466
|
-
}
|
467
|
-
);
|
468
|
-
}
|
469
|
-
);
|
542
|
+
console.log("Multiple members added!");
|
543
|
+
});
|
470
544
|
```
|
471
545
|
|
472
546
|
---
|
473
547
|
|
474
|
-
|
548
|
+
### 3.9. removeUserFromGroup - Remove Member from Group
|
475
549
|
|
476
|
-
|
550
|
+
Remove user from group chat.
|
477
551
|
|
478
|
-
|
479
|
-
|
480
|
-
|
552
|
+
#### Syntax:
|
553
|
+
```javascript
|
554
|
+
api.removeUserFromGroup(userID, threadID, callback);
|
555
|
+
```
|
481
556
|
|
482
|
-
|
483
|
-
- `callback(err)`: A callback called when the query is done (either with an error or null).
|
557
|
+
#### Example:
|
484
558
|
|
485
|
-
|
559
|
+
```javascript
|
560
|
+
api.removeUserFromGroup("100012345678901", "1234567890", (err) => {
|
561
|
+
if (err) {
|
562
|
+
console.error("Remove user error:", err);
|
563
|
+
return;
|
564
|
+
}
|
565
|
+
console.log("Member removed successfully!");
|
566
|
+
});
|
567
|
+
```
|
486
568
|
|
487
|
-
|
488
|
-
const fs = require("fs");
|
489
|
-
const login = require("fca-unofficial");
|
569
|
+
---
|
490
570
|
|
491
|
-
|
492
|
-
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
493
|
-
(err, api) => {
|
494
|
-
if (err) return console.error(err);
|
571
|
+
### 3.10. changeNickname - Change Nickname
|
495
572
|
|
496
|
-
|
497
|
-
if (message.body) {
|
498
|
-
api.sendMessage(message.body, message.threadID, (err, messageInfo) => {
|
499
|
-
if (err) return console.error(err);
|
573
|
+
Change user's nickname in group chat.
|
500
574
|
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
});
|
505
|
-
}
|
506
|
-
);
|
575
|
+
#### Syntax:
|
576
|
+
```javascript
|
577
|
+
api.changeNickname(nickname, threadID, userID, callback);
|
507
578
|
```
|
508
579
|
|
509
|
-
|
580
|
+
#### Example:
|
510
581
|
|
511
|
-
|
582
|
+
```javascript
|
583
|
+
api.changeNickname("Admin Bot", "1234567890", "100012345678901", (err) => {
|
584
|
+
if (err) {
|
585
|
+
console.error("Change nickname error:", err);
|
586
|
+
return;
|
587
|
+
}
|
588
|
+
console.log("Nickname changed successfully!");
|
589
|
+
});
|
512
590
|
|
513
|
-
|
591
|
+
// Remove nickname (set to original name)
|
592
|
+
api.changeNickname("", "1234567890", "100012345678901", (err) => {
|
593
|
+
if (err) return console.error(err);
|
594
|
+
console.log("Nickname removed!");
|
595
|
+
});
|
596
|
+
```
|
514
597
|
|
515
|
-
|
598
|
+
---
|
516
599
|
|
517
|
-
|
600
|
+
### 3.11. markAsRead - Mark as Read
|
518
601
|
|
519
|
-
|
520
|
-
- `callback(err)` - A callback called when the operation is done, maybe with an object representing an error.
|
602
|
+
Mark message as read.
|
521
603
|
|
522
|
-
|
604
|
+
#### Syntax:
|
605
|
+
```javascript
|
606
|
+
api.markAsRead(threadID, callback);
|
607
|
+
```
|
523
608
|
|
524
|
-
|
525
|
-
const fs = require("fs");
|
526
|
-
const login = require("fca-unofficial");
|
609
|
+
#### Example:
|
527
610
|
|
528
|
-
|
529
|
-
|
530
|
-
(err, api) => {
|
611
|
+
```javascript
|
612
|
+
api.listenMqtt((err, event) => {
|
531
613
|
if (err) return console.error(err);
|
532
614
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
);
|
615
|
+
if (event.type === "message") {
|
616
|
+
// Auto mark as read
|
617
|
+
api.markAsRead(event.threadID, (err) => {
|
618
|
+
if (err) console.error("Mark as read error:", err);
|
619
|
+
});
|
620
|
+
}
|
621
|
+
});
|
538
622
|
```
|
539
623
|
|
540
624
|
---
|
541
625
|
|
542
|
-
|
626
|
+
### 3.12. markAsDelivered - Mark as Delivered
|
543
627
|
|
544
|
-
|
628
|
+
Mark message as delivered.
|
545
629
|
|
546
|
-
|
630
|
+
#### Syntax:
|
631
|
+
```javascript
|
632
|
+
api.markAsDelivered(threadID, messageID, callback);
|
633
|
+
```
|
547
634
|
|
548
|
-
|
635
|
+
#### Example:
|
549
636
|
|
550
|
-
|
551
|
-
|
552
|
-
|
637
|
+
```javascript
|
638
|
+
api.markAsDelivered("1234567890", "mid.xxx", (err) => {
|
639
|
+
if (err) {
|
640
|
+
console.error("Mark as delivered error:", err);
|
641
|
+
return;
|
642
|
+
}
|
643
|
+
console.log("Marked as delivered!");
|
644
|
+
});
|
645
|
+
```
|
553
646
|
|
554
647
|
---
|
555
648
|
|
556
|
-
|
649
|
+
### 3.13. markAsReadAll - Mark All as Read
|
650
|
+
|
651
|
+
Mark all messages as read.
|
652
|
+
|
653
|
+
#### Syntax:
|
654
|
+
```javascript
|
655
|
+
api.markAsReadAll(callback);
|
656
|
+
```
|
557
657
|
|
558
|
-
|
658
|
+
#### Example:
|
559
659
|
|
560
|
-
|
660
|
+
```javascript
|
661
|
+
api.markAsReadAll((err) => {
|
662
|
+
if (err) {
|
663
|
+
console.error("Error:", err);
|
664
|
+
return;
|
665
|
+
}
|
666
|
+
console.log("All messages marked as read!");
|
667
|
+
});
|
668
|
+
```
|
561
669
|
|
562
670
|
---
|
563
671
|
|
564
|
-
|
672
|
+
### 3.14. sendTypingIndicator - Show Typing Indicator
|
565
673
|
|
566
|
-
|
674
|
+
Display "typing..." status in chat.
|
567
675
|
|
568
|
-
|
676
|
+
#### Syntax:
|
677
|
+
```javascript
|
678
|
+
api.sendTypingIndicator(threadID, callback);
|
679
|
+
```
|
569
680
|
|
570
|
-
|
681
|
+
#### Example:
|
571
682
|
|
572
|
-
|
683
|
+
```javascript
|
684
|
+
// Show typing
|
685
|
+
api.sendTypingIndicator("1234567890", (err) => {
|
686
|
+
if (err) return console.error(err);
|
573
687
|
|
574
|
-
|
688
|
+
// After 3 seconds, send message
|
689
|
+
setTimeout(() => {
|
690
|
+
api.sendMessage("Hello!", "1234567890");
|
691
|
+
}, 3000);
|
692
|
+
});
|
575
693
|
|
576
|
-
|
694
|
+
// Or stop typing indicator
|
695
|
+
api.sendTypingIndicator("1234567890", (err) => {
|
696
|
+
if (err) return console.error(err);
|
697
|
+
}, true); // 3rd parameter is true to turn off typing
|
698
|
+
```
|
577
699
|
|
578
|
-
|
579
|
-
This can happen if, for example, Messenger does not have an image asset for the requested emoji.
|
700
|
+
---
|
580
701
|
|
581
|
-
|
702
|
+
### 3.15. unsendMessage - Unsend Message
|
582
703
|
|
583
|
-
|
584
|
-
- `size` - The width and height of the emoji image; supported sizes are 32, 64, and 128
|
585
|
-
- `pixelRatio` - The pixel ratio of the emoji image; supported ratios are '1.0' and '1.5' (default is '1.0')
|
704
|
+
Unsend/recall a sent message.
|
586
705
|
|
587
|
-
|
706
|
+
#### Syntax:
|
707
|
+
```javascript
|
708
|
+
api.unsendMessage(messageID, callback);
|
709
|
+
```
|
588
710
|
|
589
|
-
|
590
|
-
const fs = require("fs");
|
591
|
-
const login = require("fca-unofficial");
|
711
|
+
#### Example:
|
592
712
|
|
593
|
-
|
594
|
-
|
595
|
-
(err, api) => {
|
713
|
+
```javascript
|
714
|
+
api.sendMessage("This message will be deleted", "1234567890", (err, messageInfo) => {
|
596
715
|
if (err) return console.error(err);
|
597
716
|
|
598
|
-
//
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
);
|
717
|
+
// Unsend after 5 seconds
|
718
|
+
setTimeout(() => {
|
719
|
+
api.unsendMessage(messageInfo.messageID, (err) => {
|
720
|
+
if (err) {
|
721
|
+
console.error("Unsend error:", err);
|
722
|
+
return;
|
723
|
+
}
|
724
|
+
console.log("Message unsent!");
|
725
|
+
});
|
726
|
+
}, 5000);
|
727
|
+
});
|
607
728
|
```
|
608
729
|
|
609
730
|
---
|
610
731
|
|
611
|
-
|
732
|
+
### 3.16. createPoll - Create Poll
|
612
733
|
|
613
|
-
|
734
|
+
Create poll in group chat.
|
614
735
|
|
615
|
-
|
736
|
+
#### Syntax:
|
737
|
+
```javascript
|
738
|
+
api.createPoll(title, threadID, options, callback);
|
739
|
+
```
|
616
740
|
|
617
|
-
|
741
|
+
#### Example:
|
618
742
|
|
619
|
-
|
743
|
+
```javascript
|
744
|
+
const title = "Choose travel destination?";
|
745
|
+
const options = {
|
746
|
+
"Da Lat": false, // false = allow multiple choices
|
747
|
+
"Nha Trang": false,
|
748
|
+
"Phu Quoc": false
|
749
|
+
};
|
620
750
|
|
621
|
-
|
751
|
+
api.createPoll(title, "1234567890", options, (err, pollInfo) => {
|
752
|
+
if (err) {
|
753
|
+
console.error("Create poll error:", err);
|
754
|
+
return;
|
755
|
+
}
|
756
|
+
console.log("Poll created successfully!");
|
757
|
+
});
|
758
|
+
```
|
622
759
|
|
623
|
-
|
624
|
-
const fs = require("fs");
|
625
|
-
const login = require("fca-unofficial");
|
760
|
+
---
|
626
761
|
|
627
|
-
|
628
|
-
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
629
|
-
(err, api) => {
|
630
|
-
if (err) return console.error(err);
|
762
|
+
### 3.17. handleMessageRequest - Handle Message Request
|
631
763
|
|
632
|
-
|
633
|
-
if (err) return console.error(err);
|
764
|
+
Accept or decline message from stranger.
|
634
765
|
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
);
|
766
|
+
#### Syntax:
|
767
|
+
```javascript
|
768
|
+
api.handleMessageRequest(threadID, accept, callback);
|
639
769
|
```
|
640
770
|
|
641
|
-
|
771
|
+
#### Example:
|
642
772
|
|
643
|
-
|
773
|
+
```javascript
|
774
|
+
// Accept message
|
775
|
+
api.handleMessageRequest("1234567890", true, (err) => {
|
776
|
+
if (err) {
|
777
|
+
console.error("Error:", err);
|
778
|
+
return;
|
779
|
+
}
|
780
|
+
console.log("Message accepted!");
|
781
|
+
});
|
644
782
|
|
645
|
-
|
783
|
+
// Decline message
|
784
|
+
api.handleMessageRequest("1234567890", false, (err) => {
|
785
|
+
if (err) return console.error(err);
|
786
|
+
console.log("Message declined!");
|
787
|
+
});
|
788
|
+
```
|
646
789
|
|
647
|
-
|
790
|
+
---
|
648
791
|
|
649
|
-
|
792
|
+
### 3.18. muteThread - Mute Notifications
|
650
793
|
|
651
|
-
|
794
|
+
Mute or unmute notifications for conversation.
|
652
795
|
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
796
|
+
#### Syntax:
|
797
|
+
```javascript
|
798
|
+
api.muteThread(threadID, muteSeconds, callback);
|
799
|
+
```
|
657
800
|
|
658
|
-
|
801
|
+
#### Example:
|
659
802
|
|
660
|
-
|
803
|
+
```javascript
|
804
|
+
// Mute for 1 hour (3600 seconds)
|
805
|
+
api.muteThread("1234567890", 3600, (err) => {
|
806
|
+
if (err) {
|
807
|
+
console.error("Error:", err);
|
808
|
+
return;
|
809
|
+
}
|
810
|
+
console.log("Muted for 1 hour!");
|
811
|
+
});
|
661
812
|
|
662
|
-
|
663
|
-
|
813
|
+
// Mute permanently
|
814
|
+
api.muteThread("1234567890", -1, (err) => {
|
815
|
+
if (err) return console.error(err);
|
816
|
+
console.log("Muted permanently!");
|
817
|
+
});
|
664
818
|
|
665
|
-
|
666
|
-
|
819
|
+
// Unmute
|
820
|
+
api.muteThread("1234567890", 0, (err) => {
|
667
821
|
if (err) return console.error(err);
|
822
|
+
console.log("Unmuted!");
|
823
|
+
});
|
824
|
+
```
|
825
|
+
|
826
|
+
---
|
668
827
|
|
669
|
-
|
670
|
-
Since the timestamp is from a previous loaded message,
|
671
|
-
that message will be included in this history so we can discard it unless it is the first load.
|
672
|
-
*/
|
673
|
-
if (timestamp != undefined) history.pop();
|
828
|
+
### 3.19. getThreadList - Get Thread List
|
674
829
|
|
675
|
-
|
676
|
-
Handle message history
|
677
|
-
*/
|
830
|
+
Get list of conversations.
|
678
831
|
|
679
|
-
|
680
|
-
|
681
|
-
|
832
|
+
#### Syntax:
|
833
|
+
```javascript
|
834
|
+
api.getThreadList(limit, timestamp, tags, callback);
|
682
835
|
```
|
683
836
|
|
684
|
-
|
837
|
+
#### Example:
|
685
838
|
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
- `threadID`: A threadID corresponding to the target thread.
|
695
|
-
- `callback(err, info)`: If `err` is `null`, `info` will contain the following properties:
|
696
|
-
|
697
|
-
| Key | Description |
|
698
|
-
| ----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
699
|
-
| threadID | ID of the thread |
|
700
|
-
| participantIDs | Array of user IDs in the thread |
|
701
|
-
| threadName | Name of the thread. Usually the name of the user. In group chats, this will be empty if the name of the group chat is unset. |
|
702
|
-
| userInfo | An array contains info of members, which has the same structure as [`getUserInfo`](#getUserInfo), but add a key `id`, contain ID of member currently at. |
|
703
|
-
| nicknames | Map of nicknames for members of the thread. If there are no nicknames set, this will be null. |
|
704
|
-
| unreadCount | Number of unread messages |
|
705
|
-
| messageCount | Number of messages |
|
706
|
-
| imageSrc | URL to the group chat photo. Null if unset or a 1-1 thread. |
|
707
|
-
| timestamp | Timestamp of last activity |
|
708
|
-
| muteUntil | Timestamp at which the thread will no longer be muted. The timestamp will be -1 if the thread is muted indefinitely or null if the thread is not muted. |
|
709
|
-
| isGroup | boolean, true if this thread is a group thread (more than 2 participants). |
|
710
|
-
| isSubscribed | |
|
711
|
-
| folder | The folder that the thread is in. Can be one of: <ul><li>'inbox'</li><li>'archive'</li></ul> |
|
712
|
-
| isArchived | True if the thread is archived, false if not |
|
713
|
-
| cannotReplyReason | If you cannot reply to this thread, this will be a string stating why. Otherwise it will be null. |
|
714
|
-
| lastReadTimestamp | Timestamp of the last message that is marked as 'read' by the current user. |
|
715
|
-
| emoji | Object with key 'emoji' whose value is the emoji unicode character. Null if unset. |
|
716
|
-
| color | String form of the custom color in hexadecimal form. |
|
717
|
-
| adminIDs | Array of user IDs of the admins of the thread. Empty array if unset. |
|
718
|
-
| approvalMode | `true` or `false`, used to check if this group requires admin approval to add users |
|
719
|
-
| approvalQueue | Array of object that has the following keys: <ul><li>`inviterID`: ID of the user invited the person to the group</li><li>`requesterID`: ID of the person waiting to be approved</li><li>`timestamp`: Request timestamp</li></ul> |
|
839
|
+
```javascript
|
840
|
+
// Get 20 most recent conversations
|
841
|
+
api.getThreadList(20, null, ["INBOX"], (err, threads) => {
|
842
|
+
if (err) {
|
843
|
+
console.error("Error:", err);
|
844
|
+
return;
|
845
|
+
}
|
720
846
|
|
721
|
-
|
847
|
+
threads.forEach(thread => {
|
848
|
+
console.log("Thread ID:", thread.threadID);
|
849
|
+
console.log("Name:", thread.name);
|
850
|
+
console.log("Unread count:", thread.unreadCount);
|
851
|
+
console.log("Last message:", thread.snippet);
|
852
|
+
console.log("---");
|
853
|
+
});
|
854
|
+
});
|
722
855
|
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
**Arguments**
|
730
|
-
|
731
|
-
- `limit`: Limit the number of threads to fetch.
|
732
|
-
- `timestamp`: Request threads _before_ this date. `null` means _now_
|
733
|
-
- `tags`: An array describing which folder to fetch. It should be one of these:
|
734
|
-
- `["INBOX"]` _(same as `[]`)_
|
735
|
-
- `["ARCHIVED"]`
|
736
|
-
- `["PENDING"]`
|
737
|
-
- `["OTHER"]`
|
738
|
-
- `["INBOX", "unread"]`
|
739
|
-
- `["ARCHIVED", "unread"]`
|
740
|
-
- `["PENDING", "unread"]`
|
741
|
-
- `["OTHER", "unread"]`
|
742
|
-
|
743
|
-
_if you find something new, let us know_
|
744
|
-
|
745
|
-
- `callback(err, list)`: Callback called when the query is done (either with an error or with a proper result). `list` is an _array_ with objects with the following properties:
|
746
|
-
|
747
|
-
**Thread list**
|
748
|
-
|
749
|
-
| Key | Description |
|
750
|
-
| -------------------- | ----------------------------------------------------------------------------------- |
|
751
|
-
| threadID | ID of the thread |
|
752
|
-
| name | The name of the thread |
|
753
|
-
| unreadCount | Amount of unread messages in thread |
|
754
|
-
| messageCount | Amount of messages in thread |
|
755
|
-
| imageSrc | Link to the thread's image or `null` |
|
756
|
-
| emoji | The default emoji in thread (classic like is `null`) |
|
757
|
-
| color | Thread's message color in `RRGGBB` (default blue is `null`) |
|
758
|
-
| nicknames | An array of `{"userid": "1234", "nickname": "John Doe"}` |
|
759
|
-
| muteUntil | Timestamp until the mute expires or `null` |
|
760
|
-
| participants | An array of participants. See below |
|
761
|
-
| adminIDs | An array of thread admin IDs |
|
762
|
-
| folder | `INBOX`, `ARCHIVED`, `PENDING` or `OTHER` |
|
763
|
-
| isGroup | `true` or `false` |
|
764
|
-
| customizationEnabled | `false` in one-to-one conversations with `Page` or `ReducedMessagingActor` |
|
765
|
-
| participantAddMode | currently `"ADD"` for groups and `null` otherwise |
|
766
|
-
| reactionsMuteMode | `REACTIONS_NOT_MUTED` or `REACTIONS_MUTED` |
|
767
|
-
| mentionsMuteMode | `MENTIONS_NOT_MUTED` or `MENTIONS_MUTED` |
|
768
|
-
| isArchived | `true` or `false` |
|
769
|
-
| isSubscribed | `true` or `false` |
|
770
|
-
| timestamp | timestamp in miliseconds |
|
771
|
-
| snippet | Snippet's text message |
|
772
|
-
| snippetAttachments | Attachments in snippet |
|
773
|
-
| snippetSender | ID of snippet sender |
|
774
|
-
| lastMessageTimestamp | timestamp in milliseconds |
|
775
|
-
| lastReadTimestamp | timestamp in milliseconds or `null` |
|
776
|
-
| cannotReplyReason | `null`, `"RECIPIENTS_NOT_LOADABLE"` or `"BLOCKED"` |
|
777
|
-
| approvalMode | `true` or `false`, used to check if this group requires admin approval to add users |
|
778
|
-
|
779
|
-
**`participants` format**
|
780
|
-
|
781
|
-
`accountType` is one of the following:
|
782
|
-
|
783
|
-
- `"User"`
|
784
|
-
- `"Page"`
|
785
|
-
- `"UnavailableMessagingActor"`
|
786
|
-
- `"ReducedMessagingActor"`
|
787
|
-
|
788
|
-
(_there might be more_)
|
789
|
-
|
790
|
-
<table>
|
791
|
-
<tr>
|
792
|
-
<th>Account type</th>
|
793
|
-
<th>Key</th>
|
794
|
-
<th>Description</th>
|
795
|
-
</tr>
|
796
|
-
<tr>
|
797
|
-
<td rowspan="12"><code>"User"</code></td>
|
798
|
-
<td>userID</td>
|
799
|
-
<td>ID of user</td>
|
800
|
-
</tr>
|
801
|
-
<tr>
|
802
|
-
<td>name</td>
|
803
|
-
<td>Full name of user</td>
|
804
|
-
</tr>
|
805
|
-
<tr>
|
806
|
-
<td>shortName</td>
|
807
|
-
<td>Short name of user (most likely first name)</td>
|
808
|
-
</tr>
|
809
|
-
<tr>
|
810
|
-
<td>gender</td>
|
811
|
-
<td>Either
|
812
|
-
<code>"MALE"</code>,
|
813
|
-
<code>"FEMALE"</code>,
|
814
|
-
<code>"NEUTER"</code> or
|
815
|
-
<code>"UNKNOWN"</code>
|
816
|
-
</td>
|
817
|
-
</tr>
|
818
|
-
<tr>
|
819
|
-
<td>url</td>
|
820
|
-
<td>URL of the user's Facebook profile</td>
|
821
|
-
</tr>
|
822
|
-
<tr>
|
823
|
-
<td>profilePicture</td>
|
824
|
-
<td>URL of the profile picture</td>
|
825
|
-
</tr>
|
826
|
-
<tr>
|
827
|
-
<td>username</td>
|
828
|
-
<td>Username of user or
|
829
|
-
<code>null</code>
|
830
|
-
</td>
|
831
|
-
</tr>
|
832
|
-
<tr>
|
833
|
-
<td>isViewerFriend</td>
|
834
|
-
<td>Is the user a friend of you?</td>
|
835
|
-
</tr>
|
836
|
-
<tr>
|
837
|
-
<td>isMessengerUser</td>
|
838
|
-
<td>Does the user use Messenger?</td>
|
839
|
-
</tr>
|
840
|
-
<tr>
|
841
|
-
<td>isVerified</td>
|
842
|
-
<td>Is the user verified? (Little blue tick mark)</td>
|
843
|
-
</tr>
|
844
|
-
<tr>
|
845
|
-
<td>isMessageBlockedByViewer</td>
|
846
|
-
<td>Is the user blocking messages from you?</td>
|
847
|
-
</tr>
|
848
|
-
<tr>
|
849
|
-
<td>isViewerCoworker</td>
|
850
|
-
<td>Is the user your coworker?
|
851
|
-
</td>
|
852
|
-
</tr>
|
853
|
-
|
854
|
-
<tr>
|
855
|
-
<td rowspan="10"><code>"Page"</code></td>
|
856
|
-
<td>userID</td>
|
857
|
-
<td>ID of the page</td>
|
858
|
-
</tr>
|
859
|
-
<tr>
|
860
|
-
<td>name</td>
|
861
|
-
<td>Name of the fanpage</td>
|
862
|
-
</tr>
|
863
|
-
<tr>
|
864
|
-
<td>url</td>
|
865
|
-
<td>URL of the fanpage</td>
|
866
|
-
</tr>
|
867
|
-
<tr>
|
868
|
-
<td>profilePicture</td>
|
869
|
-
<td>URL of the profile picture</td>
|
870
|
-
</tr>
|
871
|
-
<tr>
|
872
|
-
<td>username</td>
|
873
|
-
<td>Username of user or
|
874
|
-
<code>null</code>
|
875
|
-
</td>
|
876
|
-
</tr>
|
877
|
-
<tr>
|
878
|
-
<td>acceptsMessengerUserFeedback</td>
|
879
|
-
<td></td>
|
880
|
-
</tr>
|
881
|
-
<tr>
|
882
|
-
<td>isMessengerUser</td>
|
883
|
-
<td>Does the fanpage use Messenger?</td>
|
884
|
-
</tr>
|
885
|
-
<tr>
|
886
|
-
<td>isVerified</td>
|
887
|
-
<td>Is the fanpage verified? (Little blue tick mark)</td>
|
888
|
-
</tr>
|
889
|
-
<tr>
|
890
|
-
<td>isMessengerPlatformBot</td>
|
891
|
-
<td>Is the fanpage a bot</td>
|
892
|
-
</tr>
|
893
|
-
<tr>
|
894
|
-
<td>isMessageBlockedByViewer</td>
|
895
|
-
<td>Is the fanpage blocking messages from you?</td>
|
896
|
-
</tr>
|
897
|
-
|
898
|
-
<tr>
|
899
|
-
<td rowspan="7"><code>"ReducedMessagingActor"</code><br />(account requres verification,<br />messages are hidden)</td>
|
900
|
-
<td>userID</td>
|
901
|
-
<td>ID of the user</td>
|
902
|
-
</tr>
|
903
|
-
<tr>
|
904
|
-
<td>name</td>
|
905
|
-
<td>Name of the user</td>
|
906
|
-
</tr>
|
907
|
-
<tr>
|
908
|
-
<td>url</td>
|
909
|
-
<td>
|
910
|
-
<code>null</code>
|
911
|
-
</td>
|
912
|
-
</tr>
|
913
|
-
<tr>
|
914
|
-
<td>profilePicture</td>
|
915
|
-
<td>URL of the default Facebook profile picture</td>
|
916
|
-
</tr>
|
917
|
-
<tr>
|
918
|
-
<td>username</td>
|
919
|
-
<td>Username of user</td>
|
920
|
-
</td>
|
921
|
-
</tr>
|
922
|
-
<tr>
|
923
|
-
<td>acceptsMessengerUserFeedback</td>
|
924
|
-
<td></td>
|
925
|
-
</tr>
|
926
|
-
<tr>
|
927
|
-
<td>isMessageBlockedByViewer</td>
|
928
|
-
<td>Is the user blocking messages from you?</td>
|
929
|
-
</tr>
|
930
|
-
<tr>
|
931
|
-
<td rowspan="7"><code>"UnavailableMessagingActor"</code><br />(account disabled/removed)</td>
|
932
|
-
<td>userID</td>
|
933
|
-
<td>ID of the user</td>
|
934
|
-
</tr>
|
935
|
-
<tr>
|
936
|
-
<td>name</td>
|
937
|
-
<td><em>Facebook User</em> in user's language</td>
|
938
|
-
</tr>
|
939
|
-
<tr>
|
940
|
-
<td>url</td>
|
941
|
-
<td><code>null</code></td>
|
942
|
-
</tr>
|
943
|
-
<tr>
|
944
|
-
<td>profilePicture</td>
|
945
|
-
<td>URL of the default **male** Facebook profile picture</td>
|
946
|
-
</tr>
|
947
|
-
<tr>
|
948
|
-
<td>username</td>
|
949
|
-
<td><code>null</code></td>
|
950
|
-
</tr>
|
951
|
-
<tr>
|
952
|
-
<td>acceptsMessengerUserFeedback</td>
|
953
|
-
<td></td>
|
954
|
-
</tr>
|
955
|
-
<tr>
|
956
|
-
<td>isMessageBlockedByViewer</td>
|
957
|
-
<td>Is the user blocking messages from you?</td>
|
958
|
-
</tr>
|
959
|
-
</table>
|
960
|
-
|
961
|
-
In a case that some account type is not supported, we return just this _(but you can't rely on it)_ and log a warning to the console:
|
962
|
-
|
963
|
-
| Key | Description |
|
964
|
-
| ----------- | --------------------- |
|
965
|
-
| accountType | type, can be anything |
|
966
|
-
| userID | ID of the account |
|
967
|
-
| name | Name of the account |
|
856
|
+
// Tags can be:
|
857
|
+
// - "INBOX" : Inbox
|
858
|
+
// - "ARCHIVED" : Archived
|
859
|
+
// - "PENDING" : Pending messages
|
860
|
+
// - "OTHER" : Other
|
861
|
+
```
|
968
862
|
|
969
863
|
---
|
970
864
|
|
971
|
-
|
865
|
+
### 3.20. getThreadHistory - Get Message History
|
972
866
|
|
973
|
-
|
867
|
+
Get message history of conversation.
|
974
868
|
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
- `threadID`: A threadID corresponding to the target chat
|
980
|
-
- `offset`: Start index of picture to retrieve, where 0 is the most recent picture
|
981
|
-
- `limit`: Number of pictures to get, incrementing from the offset index
|
982
|
-
- `callback(err, arr)`: A callback called when the query is done (either with an error or with an confirmation object). `arr` is an array of objects with `uri`, `width`, and `height`.
|
869
|
+
#### Syntax:
|
870
|
+
```javascript
|
871
|
+
api.getThreadHistory(threadID, amount, timestamp, callback);
|
872
|
+
```
|
983
873
|
|
984
|
-
|
874
|
+
#### Example:
|
985
875
|
|
986
|
-
|
876
|
+
```javascript
|
877
|
+
// Get 50 most recent messages
|
878
|
+
api.getThreadHistory("1234567890", 50, null, (err, history) => {
|
879
|
+
if (err) {
|
880
|
+
console.error("Error:", err);
|
881
|
+
return;
|
882
|
+
}
|
987
883
|
|
988
|
-
|
884
|
+
history.forEach(msg => {
|
885
|
+
console.log("From:", msg.senderName);
|
886
|
+
console.log("Content:", msg.body);
|
887
|
+
console.log("Time:", new Date(msg.timestamp));
|
888
|
+
console.log("---");
|
889
|
+
});
|
890
|
+
});
|
989
891
|
|
990
|
-
|
892
|
+
// Get older messages (pagination)
|
893
|
+
const oldestTimestamp = history[history.length - 1].timestamp;
|
894
|
+
api.getThreadHistory("1234567890", 50, oldestTimestamp, (err, olderHistory) => {
|
895
|
+
if (err) return console.error(err);
|
896
|
+
console.log("Retrieved 50 older messages!");
|
897
|
+
});
|
898
|
+
```
|
991
899
|
|
992
|
-
|
900
|
+
---
|
993
901
|
|
994
|
-
|
995
|
-
- `callback(err, obj)` - A callback called when the search is done (either with an error or with the resulting object). `obj` is an array which contains all of the items that facebook graph search found, ordered by "importance". Each item in the array has the following properties: `userID`,`photoUrl`,`indexRank`, `name`, `isVerified`, `profileUrl`, `category`, `score`, `type` (type is generally user, group, page, event or app).
|
902
|
+
### 3.21. getThreadPictures - Get Thread Pictures
|
996
903
|
|
997
|
-
|
904
|
+
Get conversation/group avatar URL.
|
998
905
|
|
999
|
-
|
1000
|
-
|
1001
|
-
|
906
|
+
#### Syntax:
|
907
|
+
```javascript
|
908
|
+
api.getThreadPictures(threadID, offset, limit, callback);
|
909
|
+
```
|
1002
910
|
|
1003
|
-
|
1004
|
-
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
1005
|
-
(err, api) => {
|
1006
|
-
if (err) return console.error(err);
|
911
|
+
#### Example:
|
1007
912
|
|
1008
|
-
|
1009
|
-
|
913
|
+
```javascript
|
914
|
+
api.getThreadPictures("1234567890", 0, 10, (err, pictures) => {
|
915
|
+
if (err) {
|
916
|
+
console.error("Error:", err);
|
917
|
+
return;
|
918
|
+
}
|
1010
919
|
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
920
|
+
pictures.forEach(pic => {
|
921
|
+
console.log("Image URL:", pic.url);
|
922
|
+
console.log("Width:", pic.width);
|
923
|
+
console.log("Height:", pic.height);
|
1015
924
|
});
|
1016
|
-
|
1017
|
-
);
|
925
|
+
});
|
1018
926
|
```
|
1019
927
|
|
1020
928
|
---
|
1021
929
|
|
1022
|
-
|
930
|
+
### 3.22. getUserID - Get User ID
|
1023
931
|
|
1024
|
-
|
932
|
+
Get User ID from username or profile URL.
|
1025
933
|
|
1026
|
-
|
934
|
+
#### Syntax:
|
935
|
+
```javascript
|
936
|
+
api.getUserID(name, callback);
|
937
|
+
```
|
1027
938
|
|
1028
|
-
|
939
|
+
#### Example:
|
1029
940
|
|
1030
|
-
|
1031
|
-
|
941
|
+
```javascript
|
942
|
+
// From username
|
943
|
+
api.getUserID("john.doe", (err, data) => {
|
944
|
+
if (err) {
|
945
|
+
console.error("Error:", err);
|
946
|
+
return;
|
947
|
+
}
|
948
|
+
console.log("User ID:", data.userID);
|
949
|
+
});
|
1032
950
|
|
1033
|
-
|
951
|
+
// From profile URL
|
952
|
+
api.getUserID("https://facebook.com/john.doe", (err, data) => {
|
953
|
+
if (err) return console.error(err);
|
954
|
+
console.log("User ID:", data.userID);
|
955
|
+
});
|
956
|
+
```
|
1034
957
|
|
1035
|
-
|
1036
|
-
const fs = require("fs");
|
1037
|
-
const login = require("fca-unofficial");
|
958
|
+
---
|
1038
959
|
|
1039
|
-
|
1040
|
-
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
1041
|
-
(err, api) => {
|
1042
|
-
if (err) return console.error(err);
|
960
|
+
### 3.23. getAppState - Get Current AppState
|
1043
961
|
|
1044
|
-
|
1045
|
-
if (err) return console.error(err);
|
962
|
+
Get current AppState (cookies, session).
|
1046
963
|
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
}
|
1051
|
-
}
|
1052
|
-
});
|
1053
|
-
}
|
1054
|
-
);
|
964
|
+
#### Syntax:
|
965
|
+
```javascript
|
966
|
+
const appState = api.getAppState();
|
1055
967
|
```
|
1056
968
|
|
1057
|
-
|
969
|
+
#### Example:
|
1058
970
|
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
- Yellow: `174636906462322`
|
1075
|
-
- TealBlue: `1928399724138152`
|
1076
|
-
- Aqua: `417639218648241`
|
1077
|
-
- Mango: `930060997172551`
|
1078
|
-
- Berry: `164535220883264`
|
1079
|
-
- Citrus: `370940413392601`
|
1080
|
-
- Candy: `205488546921017`
|
1081
|
-
- ~~StarWars: `809305022860427`~~ (Facebook removed it.)
|
971
|
+
```javascript
|
972
|
+
const fs = require("fs");
|
973
|
+
|
974
|
+
// Get and save AppState
|
975
|
+
const appState = api.getAppState();
|
976
|
+
fs.writeFileSync("appstate.json", JSON.stringify(appState, null, 2));
|
977
|
+
console.log("✅ AppState saved!");
|
978
|
+
|
979
|
+
// Periodically update AppState (every 10 minutes)
|
980
|
+
setInterval(() => {
|
981
|
+
const updatedAppState = api.getAppState();
|
982
|
+
fs.writeFileSync("appstate.json", JSON.stringify(updatedAppState, null, 2));
|
983
|
+
console.log("🔄 AppState updated");
|
984
|
+
}, 10 * 60 * 1000);
|
985
|
+
```
|
1082
986
|
|
1083
987
|
---
|
1084
988
|
|
1085
|
-
|
989
|
+
### 3.24. deleteMessage - Delete Message (from your side)
|
1086
990
|
|
1087
|
-
|
991
|
+
Delete message from your side (not unsend).
|
1088
992
|
|
1089
|
-
|
993
|
+
#### Syntax:
|
994
|
+
```javascript
|
995
|
+
api.deleteMessage(messageID, callback);
|
996
|
+
```
|
1090
997
|
|
1091
|
-
|
998
|
+
#### Example:
|
1092
999
|
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1000
|
+
```javascript
|
1001
|
+
api.deleteMessage("mid.xxx", (err) => {
|
1002
|
+
if (err) {
|
1003
|
+
console.error("Delete message error:", err);
|
1004
|
+
return;
|
1005
|
+
}
|
1006
|
+
console.log("Message deleted!");
|
1007
|
+
});
|
1008
|
+
```
|
1096
1009
|
|
1097
1010
|
---
|
1098
1011
|
|
1099
|
-
|
1100
|
-
|
1101
|
-
### api.listen([callback])
|
1102
|
-
|
1103
|
-
<a name="listenMqtt"></a>
|
1104
|
-
|
1105
|
-
### api.listenMqtt([callback])
|
1106
|
-
|
1107
|
-
Will call `callback` when a new message is received on this account.
|
1108
|
-
By default this won't receive events (joining/leaving a chat, title change etc...) but it can be activated with `api.setOptions({listenEvents: true})`. This will by default ignore messages sent by the current account, you can enable listening to your own messages with `api.setOptions({selfListen: true})`. This returns an `EventEmitter` that contains function `stopListening` that will stop the `listen` loop and is guaranteed to prevent any future calls to the callback given to `listen`. An immediate call to `stopListening` when an error occurs will prevent the listen function to continue.
|
1109
|
-
|
1110
|
-
If `callback` is not defined, or isn't a `Function`, you can listen to messages with event `message` and `error` from `EventEmitter` returned by this function.
|
1111
|
-
|
1112
|
-
**Arguments**
|
1113
|
-
|
1114
|
-
- `callback(error, message)`: A callback called every time the logged-in account receives a new message.
|
1115
|
-
|
1116
|
-
<a name="message"></a>
|
1117
|
-
**Message**
|
1118
|
-
|
1119
|
-
The message object will contain different fields based on its type (as determined by its `type` field). By default, the only type that will be listened for is `message`. If enabled through [setOptions](#setOptions), the message object may alternatively represent an event e.g. a read receipt. The available event types are as follows:
|
1120
|
-
|
1121
|
-
<table>
|
1122
|
-
<tr>
|
1123
|
-
<th>Event Type</th>
|
1124
|
-
<th>Field</th>
|
1125
|
-
<th>Description</th>
|
1126
|
-
</tr>
|
1127
|
-
<tr>
|
1128
|
-
<td rowspan="10">
|
1129
|
-
<code>"message"</code><br />
|
1130
|
-
A message was sent to a thread.
|
1131
|
-
</td>
|
1132
|
-
<td><code>attachments</code></td>
|
1133
|
-
<td>An array of attachments to the message. Attachments vary in type, see the attachments table below.</td>
|
1134
|
-
</tr>
|
1135
|
-
<tr>
|
1136
|
-
<td><code>body</code></td>
|
1137
|
-
<td>The string corresponding to the message that was just received.</td>
|
1138
|
-
</tr>
|
1139
|
-
<tr>
|
1140
|
-
<td><code>isGroup</code></td>
|
1141
|
-
<td>boolean, true if this thread is a group thread (more than 2 participants).</td>
|
1142
|
-
</tr>
|
1143
|
-
<tr>
|
1144
|
-
<td><code>mentions</code></td>
|
1145
|
-
<td>An object containing people mentioned/tagged in the message in the format { id: name }</td>
|
1146
|
-
</tr>
|
1147
|
-
<tr>
|
1148
|
-
<td><code>messageID</code></td>
|
1149
|
-
<td>A string representing the message ID.</td>
|
1150
|
-
</tr>
|
1151
|
-
<tr>
|
1152
|
-
<td><code>senderID</code></td>
|
1153
|
-
<td>The id of the person who sent the message in the chat with threadID.</td>
|
1154
|
-
</tr>
|
1155
|
-
<tr>
|
1156
|
-
<td><code>threadID</code></td>
|
1157
|
-
<td>The threadID representing the thread in which the message was sent.</td>
|
1158
|
-
</tr>
|
1159
|
-
<tr>
|
1160
|
-
<td><code>isUnread</code></td>
|
1161
|
-
<td>Boolean representing whether or not the message was read.</td>
|
1162
|
-
</tr>
|
1163
|
-
<tr>
|
1164
|
-
<td><code>participantIDs</code></td>
|
1165
|
-
<td>An array containing participant IDs.</td>
|
1166
|
-
</tr>
|
1167
|
-
<tr>
|
1168
|
-
<td><code>type</code></td>
|
1169
|
-
<td>For this event type, this will always be the string <code>"message"</code>.</td>
|
1170
|
-
</tr>
|
1171
|
-
<tr>
|
1172
|
-
<td rowspan="7">
|
1173
|
-
<code>"event"</code><br />
|
1174
|
-
An event occurred within a thread. Note that receiving this event type needs to be enabled with `api.setOptions({ listenEvents: true })`
|
1175
|
-
</td>
|
1176
|
-
<td><code>author</code></td>
|
1177
|
-
<td>The person who performed the event.</td>
|
1178
|
-
</tr>
|
1179
|
-
<tr>
|
1180
|
-
<td><code>logMessageBody</code></td>
|
1181
|
-
<td>String printed in the chat.</td>
|
1182
|
-
</tr>
|
1183
|
-
<tr>
|
1184
|
-
<td><code>logMessageData</code></td>
|
1185
|
-
<td>Data relevant to the event.</td>
|
1186
|
-
</tr>
|
1187
|
-
<tr>
|
1188
|
-
<td><code>logMessageType</code></td>
|
1189
|
-
<td>String representing the type of event (<code>log:subscribe</code>, <code>log:unsubscribe</code>, <code>log:thread-name</code>, <code>log:thread-color</code>, <code>log:thread-icon</code>, <code>log:user-nickname</code>, <code>log:thread-call</code>, <code>log:thread-admins</code>)</td>
|
1190
|
-
</tr>
|
1191
|
-
<tr>
|
1192
|
-
<td><code>threadID</code></td>
|
1193
|
-
<td>The threadID representing the thread in which the message was sent.</td>
|
1194
|
-
</tr>
|
1195
|
-
<tr>
|
1196
|
-
<td><code>participantIDs</code></td>
|
1197
|
-
<td>An array containing participant IDs.</td>
|
1198
|
-
</tr>
|
1199
|
-
<tr>
|
1200
|
-
<td><code>type</code></td>
|
1201
|
-
<td>For this event type, this will always be the string <code>"event"</code>.</td>
|
1202
|
-
</tr>
|
1203
|
-
<tr>
|
1204
|
-
<td rowspan="5">
|
1205
|
-
<code>"typ"</code><br />
|
1206
|
-
A user in a thread is typing. Note that receiving this event type needs to be enabled with `api.setOptions({ listenTyping: true })`
|
1207
|
-
</td>
|
1208
|
-
<td><code>from</code></td>
|
1209
|
-
<td>ID of the user who started/stopped typing.</td>
|
1210
|
-
</tr>
|
1211
|
-
<tr>
|
1212
|
-
<td><code>fromMobile</code></td>
|
1213
|
-
<td>Boolean representing whether or not the person's using a mobile device to type.</td>
|
1214
|
-
</tr>
|
1215
|
-
<tr>
|
1216
|
-
<td><code>isTyping</code></td>
|
1217
|
-
<td>Boolean representing whether or not a person started typing.</td>
|
1218
|
-
</tr>
|
1219
|
-
<tr>
|
1220
|
-
<td><code>threadID</code></td>
|
1221
|
-
<td>The threadID representing the thread in which a user is typing.</td>
|
1222
|
-
</tr>
|
1223
|
-
<tr>
|
1224
|
-
<td><code>type</code></td>
|
1225
|
-
<td>For this event type, this will always be the string <code>"typ"</code>.</td>
|
1226
|
-
</tr>
|
1227
|
-
<tr>
|
1228
|
-
<td rowspan="3">
|
1229
|
-
<code>"read"</code><br />
|
1230
|
-
The current API user has read a message.
|
1231
|
-
</td>
|
1232
|
-
<td><code>threadID</code></td>
|
1233
|
-
<td>The threadID representing the thread in which the message was sent.</td>
|
1234
|
-
</tr>
|
1235
|
-
<tr>
|
1236
|
-
<td><code>time</code></td>
|
1237
|
-
<td>The time at which the user read the message.</td>
|
1238
|
-
</tr>
|
1239
|
-
<tr>
|
1240
|
-
<td><code>type</code></td>
|
1241
|
-
<td>For this event type, this will always be the string <code>"read"</code>.</td>
|
1242
|
-
</tr>
|
1243
|
-
<tr>
|
1244
|
-
<td rowspan="4">
|
1245
|
-
<code>"read_receipt"</code><br />
|
1246
|
-
A user within a thread has seen a message sent by the API user.
|
1247
|
-
</td>
|
1248
|
-
<td><code>reader</code></td>
|
1249
|
-
<td>ID of the user who just read the message.</td>
|
1250
|
-
</tr>
|
1251
|
-
<tr>
|
1252
|
-
<td><code>threadID</code></td>
|
1253
|
-
<td>The thread in which the message was read.</td>
|
1254
|
-
</tr>
|
1255
|
-
<tr>
|
1256
|
-
<td><code>time</code></td>
|
1257
|
-
<td>The time at which the reader read the message.</td>
|
1258
|
-
</tr>
|
1259
|
-
<tr>
|
1260
|
-
<td><code>type</code></td>
|
1261
|
-
<td>For this event type, this will always be the string <code>"read_receipt"</code>.</td>
|
1262
|
-
</tr>
|
1263
|
-
<tr>
|
1264
|
-
<td rowspan="8">
|
1265
|
-
<code>"message_reaction"</code><br />
|
1266
|
-
A user has sent a reaction to a message.
|
1267
|
-
</td>
|
1268
|
-
<td><code>messageID</code></td>
|
1269
|
-
<td>The ID of the message</td>
|
1270
|
-
</tr>
|
1271
|
-
<tr>
|
1272
|
-
<td><code>offlineThreadingID</code></td>
|
1273
|
-
<td>The offline message ID</td>
|
1274
|
-
</tr>
|
1275
|
-
<tr>
|
1276
|
-
<td><code>reaction</code></td>
|
1277
|
-
<td>Contains reaction emoji</td>
|
1278
|
-
</tr>
|
1279
|
-
<tr>
|
1280
|
-
<td><code>senderID</code></td>
|
1281
|
-
<td>ID of the author the message, where has been reaction added</td>
|
1282
|
-
</tr>
|
1283
|
-
<tr>
|
1284
|
-
<td><code>threadID</code></td>
|
1285
|
-
<td>ID of the thread where the message has been sent</td>
|
1286
|
-
</tr>
|
1287
|
-
<tr>
|
1288
|
-
<td><code>timestamp</code></td>
|
1289
|
-
<td>Unix Timestamp (in miliseconds) when the reaction was sent</td>
|
1290
|
-
</tr>
|
1291
|
-
<tr>
|
1292
|
-
<td><code>type</code></td>
|
1293
|
-
<td>For this event type, this will always be the string <code>"message_reaction"</code>.</td>
|
1294
|
-
</tr>
|
1295
|
-
<tr>
|
1296
|
-
<td><code>userID</code></td>
|
1297
|
-
<td>ID of the reaction sender</td>
|
1298
|
-
</tr>
|
1299
|
-
<tr>
|
1300
|
-
<td rowspan="4"><a name="presence"></a>
|
1301
|
-
<code>"presence"</code><br />
|
1302
|
-
The online status of the user's friends. Note that receiving this event type needs to be enabled with <code>api.setOptions({ updatePresence: true })</code>
|
1303
|
-
</td>
|
1304
|
-
<td><code>statuses</code></td>
|
1305
|
-
<td>The online status of the user. <code>0</code> means the user is idle (away for 2 minutes) and <code>2</code> means the user is online (we don't know what 1 or above 2 means...).</td>
|
1306
|
-
</tr>
|
1307
|
-
<tr>
|
1308
|
-
<td><code>timestamp</code></td>
|
1309
|
-
<td>The time when the user was last online.</td>
|
1310
|
-
</tr>
|
1311
|
-
<tr>
|
1312
|
-
<td><code>type</code></td>
|
1313
|
-
<td>For this event type, this will always be the string <code>"presence"</code>.</td>
|
1314
|
-
</tr>
|
1315
|
-
<tr>
|
1316
|
-
<td><code>userID</code></td>
|
1317
|
-
<td>The ID of the user whose status this packet is describing.</td>
|
1318
|
-
</tr>
|
1319
|
-
<tr>
|
1320
|
-
<td rowspan="5">
|
1321
|
-
<code>"message_unsend"</code><br />
|
1322
|
-
A revoke message request for a message from a thread was received.
|
1323
|
-
</td>
|
1324
|
-
<td><code>threadID</code></td>
|
1325
|
-
<td>The threadID representing the thread in which the revoke message request was received.</td>
|
1326
|
-
</tr>
|
1327
|
-
<tr>
|
1328
|
-
<td><code>senderID</code></td>
|
1329
|
-
<td>The id of the person who request to revoke message on threadID.</td>
|
1330
|
-
</tr>
|
1331
|
-
<tr>
|
1332
|
-
<td><code>messageID</code></td>
|
1333
|
-
<td>A string representing the message ID that the person request to revoke message want to.</td>
|
1334
|
-
</tr>
|
1335
|
-
<tr>
|
1336
|
-
<td><code>deletionTimestamp</code></td>
|
1337
|
-
<td>The time when the request was sent.</td>
|
1338
|
-
</tr>
|
1339
|
-
<tr>
|
1340
|
-
<td><code>type</code></td>
|
1341
|
-
<td>For this event type, this will always be the string <code>"message_unsend"</code>.</td>
|
1342
|
-
</tr>
|
1343
|
-
<tr>
|
1344
|
-
<td rowspan="11">
|
1345
|
-
<code>"message_reply"</code><br />
|
1346
|
-
A reply message was sent to a thread.
|
1347
|
-
</td>
|
1348
|
-
<td><code>attachments</code></td>
|
1349
|
-
<td>An array of attachments to the message. Attachments vary in type, see the attachments table below.</td>
|
1350
|
-
</tr>
|
1351
|
-
<tr>
|
1352
|
-
<td><code>body</code></td>
|
1353
|
-
<td>The string corresponding to the message that was just received.</td>
|
1354
|
-
</tr>
|
1355
|
-
<tr>
|
1356
|
-
<td><code>isGroup</code></td>
|
1357
|
-
<td>boolean, true if this thread is a group thread (more than 2 participants).</td>
|
1358
|
-
</tr>
|
1359
|
-
<tr>
|
1360
|
-
<td><code>mentions</code></td>
|
1361
|
-
<td>An object containing people mentioned/tagged in the message in the format { id: name }</td>
|
1362
|
-
</tr>
|
1363
|
-
<tr>
|
1364
|
-
<td><code>messageID</code></td>
|
1365
|
-
<td>A string representing the message ID.</td>
|
1366
|
-
</tr>
|
1367
|
-
<tr>
|
1368
|
-
<td><code>senderID</code></td>
|
1369
|
-
<td>The id of the person who sent the message in the chat with threadID.</td>
|
1370
|
-
</tr>
|
1371
|
-
<tr>
|
1372
|
-
<td><code>threadID</code></td>
|
1373
|
-
<td>The threadID representing the thread in which the message was sent.</td>
|
1374
|
-
</tr>
|
1375
|
-
<tr>
|
1376
|
-
<td><code>isUnread</code></td>
|
1377
|
-
<td>Boolean representing whether or not the message was read.</td>
|
1378
|
-
</tr>
|
1379
|
-
<tr>
|
1380
|
-
<td><code>type</code></td>
|
1381
|
-
<td>For this event type, this will always be the string <code>"message_reply"</code>.</td>
|
1382
|
-
</tr>
|
1383
|
-
<tr>
|
1384
|
-
<td><code>participantIDs</code></td>
|
1385
|
-
<td>An array containing participant IDs.</td>
|
1386
|
-
</tr>
|
1387
|
-
<tr>
|
1388
|
-
<td><code>messageReply</code></td>
|
1389
|
-
<td>An object represent a message being replied. Content inside is the same like a normal <code>"message"</code> event.</td>
|
1390
|
-
</tr>
|
1391
|
-
</table>
|
1392
|
-
|
1393
|
-
**Attachments**
|
1394
|
-
|
1395
|
-
Similar to how messages can vary based on their `type`, so too can the `attachments` within `"message"` events. Each attachment will consist of an object of one of the following types:
|
1396
|
-
|
1397
|
-
| Attachment Type | Fields |
|
1398
|
-
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
1399
|
-
| `"sticker"` | `ID`, `url`, `packID`, `spriteUrl`, `spriteUrl2x`, `width`, `height`, `caption`, `description`, `frameCount`, `frameRate`, `framesPerRow`, `framesPerCol` |
|
1400
|
-
| `"file"` | `ID`, `filename`, `url`, `isMalicious`, `contentType` |
|
1401
|
-
| `"photo"` | `ID`, `filename`, `thumbnailUrl`, `previewUrl`, `previewWidth`, `previewHeight`, `largePreviewUrl`, `largePreviewWidth`, `largePreviewHeight` |
|
1402
|
-
| `"animated_image"` | `ID`, `filename`, `previewUrl`, `previewWidth`, `previewHeight`, `url`, `width`, `height` |
|
1403
|
-
| `"video"` | `ID`, `filename`, `previewUrl`, `previewWidth`, `previewHeight`, `url`, `width`, `height`, `duration`, `videoType` |
|
1404
|
-
| `"audio"` | `ID`, `filename`, `audioType`, `duration`, `url`, `isVoiceMail` |
|
1405
|
-
| `"location"` | `ID`, `latitude`, `longitude`, `image`, `width`, `height`, `url`, `address` |
|
1406
|
-
| `"share"` | `ID`, `url`, `title`, `description`, `source`, `image`, `width`, `height`, `playable`, `duration`, `playableUrl`, `subattachments`, `properties` |
|
1407
|
-
|
1408
|
-
**Example**
|
1409
|
-
|
1410
|
-
```js
|
1411
|
-
const fs = require("fs");
|
1412
|
-
const login = require("fca-unofficial");
|
1012
|
+
### 3.25. deleteThread - Delete Thread
|
1413
1013
|
|
1414
|
-
|
1415
|
-
// Will stop when you say '/stop'
|
1014
|
+
Delete conversation from your list.
|
1416
1015
|
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
api.setOptions({ listenEvents: true });
|
1016
|
+
#### Syntax:
|
1017
|
+
```javascript
|
1018
|
+
api.deleteThread(threadID, callback);
|
1019
|
+
```
|
1423
1020
|
|
1424
|
-
|
1425
|
-
if (err) return console.error(err);
|
1021
|
+
#### Example:
|
1426
1022
|
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
});
|
1436
|
-
api.sendMessage("TEST BOT: " + event.body, event.threadID);
|
1437
|
-
break;
|
1438
|
-
case "event":
|
1439
|
-
console.log(event);
|
1440
|
-
break;
|
1441
|
-
}
|
1442
|
-
});
|
1443
|
-
}
|
1444
|
-
);
|
1023
|
+
```javascript
|
1024
|
+
api.deleteThread("1234567890", (err) => {
|
1025
|
+
if (err) {
|
1026
|
+
console.error("Delete thread error:", err);
|
1027
|
+
return;
|
1028
|
+
}
|
1029
|
+
console.log("Thread deleted!");
|
1030
|
+
});
|
1445
1031
|
```
|
1446
1032
|
|
1447
1033
|
---
|
1448
1034
|
|
1449
|
-
|
1035
|
+
### 3.26. forwardAttachment - Forward Attachment
|
1450
1036
|
|
1451
|
-
|
1037
|
+
Forward attachment from one message to another.
|
1452
1038
|
|
1453
|
-
|
1039
|
+
#### Syntax:
|
1040
|
+
```javascript
|
1041
|
+
api.forwardAttachment(attachmentID, userOrThreadID, callback);
|
1042
|
+
```
|
1043
|
+
|
1044
|
+
#### Example:
|
1454
1045
|
|
1455
|
-
|
1046
|
+
```javascript
|
1047
|
+
api.listenMqtt((err, event) => {
|
1048
|
+
if (err) return console.error(err);
|
1456
1049
|
|
1457
|
-
|
1050
|
+
if (event.type === "message" && event.attachments.length > 0) {
|
1051
|
+
// Forward first attachment
|
1052
|
+
const attachmentID = event.attachments[0].ID;
|
1458
1053
|
|
1459
|
-
|
1054
|
+
api.forwardAttachment(attachmentID, "100012345678901", (err) => {
|
1055
|
+
if (err) {
|
1056
|
+
console.error("Forward error:", err);
|
1057
|
+
return;
|
1058
|
+
}
|
1059
|
+
console.log("Attachment forwarded!");
|
1060
|
+
});
|
1061
|
+
}
|
1062
|
+
});
|
1063
|
+
```
|
1460
1064
|
|
1461
|
-
|
1065
|
+
---
|
1462
1066
|
|
1463
|
-
###
|
1067
|
+
### 3.27. setMessageReaction - React to Message
|
1464
1068
|
|
1465
|
-
|
1069
|
+
Add reaction (like, love, haha, wow, sad, angry) to message.
|
1466
1070
|
|
1467
|
-
|
1071
|
+
#### Syntax:
|
1072
|
+
```javascript
|
1073
|
+
api.setMessageReaction(reaction, messageID, callback);
|
1074
|
+
```
|
1468
1075
|
|
1469
|
-
|
1076
|
+
#### Example:
|
1470
1077
|
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1078
|
+
```javascript
|
1079
|
+
// Reaction can be:
|
1080
|
+
// "👍" or ":like:" - Like
|
1081
|
+
// "❤️" or ":love:" - Love
|
1082
|
+
// "😂" or ":haha:" - Haha
|
1083
|
+
// "😮" or ":wow:" - Wow
|
1084
|
+
// "😢" or ":sad:" - Sad
|
1085
|
+
// "😠" or ":angry:" - Angry
|
1086
|
+
// "" (empty string) - Remove reaction
|
1474
1087
|
|
1475
|
-
|
1088
|
+
api.listenMqtt((err, event) => {
|
1089
|
+
if (err) return console.error(err);
|
1476
1090
|
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1091
|
+
if (event.type === "message" && event.body === "React me") {
|
1092
|
+
api.setMessageReaction("❤️", event.messageID, (err) => {
|
1093
|
+
if (err) {
|
1094
|
+
console.error("React error:", err);
|
1095
|
+
return;
|
1096
|
+
}
|
1097
|
+
console.log("Message reacted!");
|
1098
|
+
});
|
1099
|
+
}
|
1100
|
+
});
|
1480
1101
|
|
1481
|
-
|
1482
|
-
|
1483
|
-
(err, api) => {
|
1102
|
+
// Remove reaction
|
1103
|
+
api.setMessageReaction("", "mid.xxx", (err) => {
|
1484
1104
|
if (err) return console.error(err);
|
1105
|
+
console.log("Reaction removed!");
|
1106
|
+
});
|
1107
|
+
```
|
1108
|
+
|
1109
|
+
---
|
1485
1110
|
|
1486
|
-
|
1487
|
-
if (err) return console.error(err);
|
1111
|
+
### 3.28. searchForThread - Search for Thread
|
1488
1112
|
|
1489
|
-
|
1490
|
-
|
1113
|
+
Search for conversation by name.
|
1114
|
+
|
1115
|
+
#### Syntax:
|
1116
|
+
```javascript
|
1117
|
+
api.searchForThread(name, callback);
|
1118
|
+
```
|
1119
|
+
|
1120
|
+
#### Example:
|
1121
|
+
|
1122
|
+
```javascript
|
1123
|
+
api.searchForThread("Study Group", (err, threads) => {
|
1124
|
+
if (err) {
|
1125
|
+
console.error("Search error:", err);
|
1126
|
+
return;
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
threads.forEach(thread => {
|
1130
|
+
console.log("Name:", thread.name);
|
1131
|
+
console.log("Thread ID:", thread.threadID);
|
1132
|
+
console.log("Type:", thread.isGroup ? "Group" : "Personal");
|
1133
|
+
console.log("---");
|
1491
1134
|
});
|
1492
|
-
|
1493
|
-
);
|
1135
|
+
});
|
1494
1136
|
```
|
1495
1137
|
|
1496
1138
|
---
|
1497
1139
|
|
1498
|
-
|
1140
|
+
### 3.29. logout - Logout
|
1141
|
+
|
1142
|
+
Logout from Facebook account.
|
1499
1143
|
|
1500
|
-
|
1144
|
+
#### Syntax:
|
1145
|
+
```javascript
|
1146
|
+
api.logout(callback);
|
1147
|
+
```
|
1501
1148
|
|
1502
|
-
|
1149
|
+
#### Example:
|
1503
1150
|
|
1504
|
-
|
1151
|
+
```javascript
|
1152
|
+
api.logout((err) => {
|
1153
|
+
if (err) {
|
1154
|
+
console.error("Logout error:", err);
|
1155
|
+
return;
|
1156
|
+
}
|
1157
|
+
console.log("Logged out successfully!");
|
1158
|
+
});
|
1159
|
+
```
|
1505
1160
|
|
1506
|
-
|
1161
|
+
---
|
1507
1162
|
|
1508
|
-
|
1509
|
-
- `read` - An optional boolean where `true` means to mark the message as being "read" and `false` means to mark the message as being "unread".
|
1510
|
-
- `callback(err)` - A callback called when the operation is done maybe with an object representing an error.
|
1163
|
+
### 3.30. getCurrentUserID - Get Current User ID
|
1511
1164
|
|
1512
|
-
|
1165
|
+
Get User ID of currently logged in account.
|
1513
1166
|
|
1514
|
-
|
1515
|
-
|
1516
|
-
const
|
1167
|
+
#### Syntax:
|
1168
|
+
```javascript
|
1169
|
+
const myUserID = api.getCurrentUserID();
|
1170
|
+
```
|
1517
1171
|
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1172
|
+
#### Example:
|
1173
|
+
|
1174
|
+
```javascript
|
1175
|
+
const myUserID = api.getCurrentUserID();
|
1176
|
+
console.log("Bot's User ID:", myUserID);
|
1177
|
+
|
1178
|
+
// Use to check if message is from bot
|
1179
|
+
api.listenMqtt((err, event) => {
|
1521
1180
|
if (err) return console.error(err);
|
1522
1181
|
|
1523
|
-
|
1524
|
-
|
1182
|
+
if (event.type === "message") {
|
1183
|
+
if (event.senderID === myUserID) {
|
1184
|
+
console.log("This is a message from bot!");
|
1185
|
+
} else {
|
1186
|
+
console.log("Message from someone else");
|
1187
|
+
}
|
1188
|
+
}
|
1189
|
+
});
|
1190
|
+
```
|
1525
1191
|
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1192
|
+
---
|
1193
|
+
|
1194
|
+
### 3.31. resolvePhotoUrl - Get High Quality Photo URL
|
1195
|
+
|
1196
|
+
Get high resolution photo URL from photo ID.
|
1197
|
+
|
1198
|
+
#### Syntax:
|
1199
|
+
```javascript
|
1200
|
+
api.resolvePhotoUrl(photoID, callback);
|
1201
|
+
```
|
1202
|
+
|
1203
|
+
#### Example:
|
1204
|
+
|
1205
|
+
```javascript
|
1206
|
+
api.resolvePhotoUrl("1234567890123456", (err, url) => {
|
1207
|
+
if (err) {
|
1208
|
+
console.error("Error:", err);
|
1209
|
+
return;
|
1210
|
+
}
|
1211
|
+
console.log("High quality image URL:", url);
|
1212
|
+
});
|
1531
1213
|
```
|
1532
1214
|
|
1533
1215
|
---
|
1534
1216
|
|
1535
|
-
|
1217
|
+
### 3.32. changeArchivedStatus - Archive/Unarchive Thread
|
1536
1218
|
|
1537
|
-
|
1219
|
+
Archive or unarchive conversation.
|
1220
|
+
|
1221
|
+
#### Syntax:
|
1222
|
+
```javascript
|
1223
|
+
api.changeArchivedStatus(threadID, archive, callback);
|
1224
|
+
```
|
1538
1225
|
|
1539
|
-
|
1226
|
+
#### Example:
|
1227
|
+
|
1228
|
+
```javascript
|
1229
|
+
// Archive conversation
|
1230
|
+
api.changeArchivedStatus("1234567890", true, (err) => {
|
1231
|
+
if (err) {
|
1232
|
+
console.error("Error:", err);
|
1233
|
+
return;
|
1234
|
+
}
|
1235
|
+
console.log("Thread archived!");
|
1236
|
+
});
|
1237
|
+
|
1238
|
+
// Unarchive
|
1239
|
+
api.changeArchivedStatus("1234567890", false, (err) => {
|
1240
|
+
if (err) return console.error(err);
|
1241
|
+
console.log("Thread unarchived!");
|
1242
|
+
});
|
1243
|
+
```
|
1540
1244
|
|
1541
1245
|
---
|
1542
1246
|
|
1543
|
-
|
1247
|
+
### 3.33. changeBlockedStatus - Block/Unblock User
|
1248
|
+
|
1249
|
+
Block or unblock user.
|
1250
|
+
|
1251
|
+
#### Syntax:
|
1252
|
+
```javascript
|
1253
|
+
api.changeBlockedStatus(userID, block, callback);
|
1254
|
+
```
|
1544
1255
|
|
1545
|
-
|
1256
|
+
#### Example:
|
1546
1257
|
|
1547
|
-
|
1258
|
+
```javascript
|
1259
|
+
// Block user
|
1260
|
+
api.changeBlockedStatus("100012345678901", true, (err) => {
|
1261
|
+
if (err) {
|
1262
|
+
console.error("Error:", err);
|
1263
|
+
return;
|
1264
|
+
}
|
1265
|
+
console.log("User blocked!");
|
1266
|
+
});
|
1267
|
+
|
1268
|
+
// Unblock
|
1269
|
+
api.changeBlockedStatus("100012345678901", false, (err) => {
|
1270
|
+
if (err) return console.error(err);
|
1271
|
+
console.log("User unblocked!");
|
1272
|
+
});
|
1273
|
+
```
|
1548
1274
|
|
1549
1275
|
---
|
1550
1276
|
|
1551
|
-
|
1277
|
+
### 3.34. createNewGroup - Create New Group
|
1278
|
+
|
1279
|
+
Create new group chat with member list.
|
1280
|
+
|
1281
|
+
#### Syntax:
|
1282
|
+
```javascript
|
1283
|
+
api.createNewGroup(participantIDs, groupTitle, callback);
|
1284
|
+
```
|
1552
1285
|
|
1553
|
-
|
1286
|
+
#### Example:
|
1554
1287
|
|
1555
|
-
|
1288
|
+
```javascript
|
1289
|
+
const members = ["100012345678901", "100012345678902", "100012345678903"];
|
1290
|
+
const groupName = "New Chat Group";
|
1556
1291
|
|
1557
|
-
|
1292
|
+
api.createNewGroup(members, groupName, (err, threadID) => {
|
1293
|
+
if (err) {
|
1294
|
+
console.error("Create group error:", err);
|
1295
|
+
return;
|
1296
|
+
}
|
1297
|
+
console.log("Group created successfully!");
|
1298
|
+
console.log("Thread ID:", threadID);
|
1558
1299
|
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1300
|
+
// Send message to new group
|
1301
|
+
api.sendMessage("Welcome to the group!", threadID);
|
1302
|
+
});
|
1303
|
+
```
|
1562
1304
|
|
1563
|
-
|
1305
|
+
---
|
1564
1306
|
|
1565
|
-
|
1307
|
+
## 4. COMPLETE BOT EXAMPLES
|
1308
|
+
|
1309
|
+
### 4.1. Echo Bot (Message Repeater)
|
1310
|
+
|
1311
|
+
```javascript
|
1566
1312
|
const fs = require("fs");
|
1567
|
-
const login = require("fca-unofficial");
|
1313
|
+
const login = require("@dongdev/fca-unofficial");
|
1568
1314
|
|
1315
|
+
// Login
|
1569
1316
|
login(
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1317
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
1318
|
+
(err, api) => {
|
1319
|
+
if (err) {
|
1320
|
+
console.error("Login error:", err);
|
1321
|
+
return;
|
1322
|
+
}
|
1573
1323
|
|
1574
|
-
|
1575
|
-
if (err) return console.error(err);
|
1324
|
+
console.log("✅ Bot started!");
|
1576
1325
|
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1326
|
+
// Configuration
|
1327
|
+
api.setOptions({
|
1328
|
+
listenEvents: true,
|
1329
|
+
selfListen: false,
|
1330
|
+
logLevel: "silent"
|
1331
|
+
});
|
1332
|
+
|
1333
|
+
// Listen for messages
|
1334
|
+
api.listenMqtt((err, event) => {
|
1335
|
+
if (err) return console.error(err);
|
1336
|
+
|
1337
|
+
if (event.type === "message") {
|
1338
|
+
const { body, threadID, messageID, senderID } = event;
|
1339
|
+
|
1340
|
+
// Stop bot command
|
1341
|
+
if (body === "/stop") {
|
1342
|
+
api.sendMessage("Bot stopped!", threadID);
|
1343
|
+
process.exit(0);
|
1344
|
+
}
|
1345
|
+
|
1346
|
+
// Echo message
|
1347
|
+
api.sendMessage(`📣 Echo: ${body}`, threadID, messageID);
|
1348
|
+
}
|
1349
|
+
});
|
1350
|
+
}
|
1581
1351
|
);
|
1582
1352
|
```
|
1583
1353
|
|
1584
1354
|
---
|
1585
1355
|
|
1586
|
-
|
1356
|
+
### 4.2. Group Management Bot
|
1587
1357
|
|
1588
|
-
|
1358
|
+
```javascript
|
1359
|
+
const fs = require("fs");
|
1360
|
+
const login = require("@dongdev/fca-unofficial");
|
1589
1361
|
|
1590
|
-
|
1362
|
+
// Admin list (User IDs)
|
1363
|
+
const ADMINS = ["100012345678901", "100012345678902"];
|
1591
1364
|
|
1592
|
-
|
1365
|
+
// Check admin permission
|
1366
|
+
function isAdmin(userID) {
|
1367
|
+
return ADMINS.includes(userID);
|
1368
|
+
}
|
1593
1369
|
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1370
|
+
login(
|
1371
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
1372
|
+
(err, api) => {
|
1373
|
+
if (err) return console.error(err);
|
1597
1374
|
|
1598
|
-
|
1375
|
+
console.log("✅ Group management bot started!");
|
1376
|
+
|
1377
|
+
api.setOptions({ listenEvents: true });
|
1378
|
+
|
1379
|
+
api.listenMqtt((err, event) => {
|
1380
|
+
if (err) return console.error(err);
|
1381
|
+
|
1382
|
+
const { type, threadID, senderID, body, messageID } = event;
|
1383
|
+
|
1384
|
+
// Handle messages
|
1385
|
+
if (type === "message") {
|
1386
|
+
// Only admins can use commands
|
1387
|
+
if (!isAdmin(senderID)) {
|
1388
|
+
if (body.startsWith("/")) {
|
1389
|
+
api.sendMessage(
|
1390
|
+
"❌ You don't have permission to use this command!",
|
1391
|
+
threadID,
|
1392
|
+
messageID
|
1393
|
+
);
|
1394
|
+
}
|
1395
|
+
return;
|
1396
|
+
}
|
1397
|
+
|
1398
|
+
// Kick command
|
1399
|
+
if (body.startsWith("/kick ")) {
|
1400
|
+
const userID = body.split(" ")[1];
|
1401
|
+
api.removeUserFromGroup(userID, threadID, (err) => {
|
1402
|
+
if (err) {
|
1403
|
+
api.sendMessage("❌ Error kicking user!", threadID);
|
1404
|
+
} else {
|
1405
|
+
api.sendMessage("✅ User kicked!", threadID);
|
1406
|
+
}
|
1407
|
+
});
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
// Rename command
|
1411
|
+
else if (body.startsWith("/rename ")) {
|
1412
|
+
const newName = body.substring(8);
|
1413
|
+
api.setTitle(newName, threadID, (err) => {
|
1414
|
+
if (err) {
|
1415
|
+
api.sendMessage("❌ Error renaming group!", threadID);
|
1416
|
+
} else {
|
1417
|
+
api.sendMessage(`✅ Group renamed to: ${newName}`, threadID);
|
1418
|
+
}
|
1419
|
+
});
|
1420
|
+
}
|
1421
|
+
|
1422
|
+
// Group info command
|
1423
|
+
else if (body === "/info") {
|
1424
|
+
api.getThreadInfo(threadID, (err, info) => {
|
1425
|
+
if (err) return api.sendMessage("❌ Error getting info!", threadID);
|
1426
|
+
|
1427
|
+
const message = `
|
1428
|
+
📊 GROUP INFORMATION
|
1429
|
+
━━━━━━━━━━━━━━━
|
1430
|
+
👥 Name: ${info.threadName}
|
1431
|
+
📝 Members: ${info.participantIDs.length}
|
1432
|
+
👑 Admins: ${info.adminIDs.length}
|
1433
|
+
🎨 Color: ${info.color}
|
1434
|
+
😊 Emoji: ${info.emoji || "Default"}
|
1435
|
+
`.trim();
|
1436
|
+
|
1437
|
+
api.sendMessage(message, threadID);
|
1438
|
+
});
|
1439
|
+
}
|
1440
|
+
|
1441
|
+
// Help command
|
1442
|
+
else if (body === "/help") {
|
1443
|
+
const helpMessage = `
|
1444
|
+
🤖 COMMAND LIST
|
1445
|
+
━━━━━━━━━━━━━━━
|
1446
|
+
/kick [userID] - Kick member
|
1447
|
+
/rename [new name] - Rename group
|
1448
|
+
/info - View group info
|
1449
|
+
/help - Show help
|
1450
|
+
`.trim();
|
1451
|
+
|
1452
|
+
api.sendMessage(helpMessage, threadID);
|
1453
|
+
}
|
1454
|
+
}
|
1599
1455
|
|
1600
|
-
|
1456
|
+
// Handle events
|
1457
|
+
else if (type === "event") {
|
1458
|
+
// Welcome new members
|
1459
|
+
if (event.logMessageType === "log:subscribe") {
|
1460
|
+
const addedUsers = event.logMessageData.addedParticipants;
|
1461
|
+
addedUsers.forEach(user => {
|
1462
|
+
api.sendMessage(
|
1463
|
+
`👋 Welcome ${user.fullName} to the group!`,
|
1464
|
+
threadID
|
1465
|
+
);
|
1466
|
+
});
|
1467
|
+
}
|
1468
|
+
|
1469
|
+
// Notify when someone leaves
|
1470
|
+
else if (event.logMessageType === "log:unsubscribe") {
|
1471
|
+
api.sendMessage(`👋 Goodbye! A member left the group.`, threadID);
|
1472
|
+
}
|
1473
|
+
}
|
1474
|
+
});
|
1475
|
+
}
|
1476
|
+
);
|
1477
|
+
```
|
1601
1478
|
|
1602
|
-
|
1479
|
+
---
|
1603
1480
|
|
1604
|
-
|
1605
|
-
of image attachments in messages, returned by [`api.getThreadHistory`](#getThreadHistory).
|
1481
|
+
### 4.3. AI ChatBot Style (Mock)
|
1606
1482
|
|
1607
|
-
|
1483
|
+
```javascript
|
1484
|
+
const fs = require("fs");
|
1485
|
+
const login = require("@dongdev/fca-unofficial");
|
1608
1486
|
|
1609
|
-
|
1610
|
-
|
1487
|
+
// Store chat history by threadID
|
1488
|
+
const chatHistory = {};
|
1611
1489
|
|
1612
|
-
|
1490
|
+
// Mock AI response function
|
1491
|
+
function getAIResponse(message, threadID) {
|
1492
|
+
// Initialize history if not exists
|
1493
|
+
if (!chatHistory[threadID]) {
|
1494
|
+
chatHistory[threadID] = [];
|
1495
|
+
}
|
1613
1496
|
|
1614
|
-
|
1497
|
+
// Add user message to history
|
1498
|
+
chatHistory[threadID].push({ role: "user", content: message });
|
1615
1499
|
|
1616
|
-
|
1500
|
+
// Limit history to last 10 messages
|
1501
|
+
if (chatHistory[threadID].length > 10) {
|
1502
|
+
chatHistory[threadID] = chatHistory[threadID].slice(-10);
|
1503
|
+
}
|
1617
1504
|
|
1618
|
-
|
1619
|
-
|
1505
|
+
// Mock response (you can integrate real ChatGPT API here)
|
1506
|
+
let response = "";
|
1507
|
+
|
1508
|
+
if (message.toLowerCase().includes("hello")) {
|
1509
|
+
response = "Hello! How can I help you?";
|
1510
|
+
} else if (message.toLowerCase().includes("name")) {
|
1511
|
+
response = "I'm an AI Assistant Bot!";
|
1512
|
+
} else if (message.toLowerCase().includes("weather")) {
|
1513
|
+
response = "Sorry, I don't have weather information. Please check weather apps!";
|
1514
|
+
} else {
|
1515
|
+
response = `I received your message: "${message}". Thank you for chatting with me!`;
|
1516
|
+
}
|
1620
1517
|
|
1621
|
-
|
1518
|
+
// Add response to history
|
1519
|
+
chatHistory[threadID].push({ role: "assistant", content: response });
|
1622
1520
|
|
1623
|
-
|
1521
|
+
return response;
|
1522
|
+
}
|
1624
1523
|
|
1625
|
-
|
1626
|
-
|
1524
|
+
login(
|
1525
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
1526
|
+
(err, api) => {
|
1527
|
+
if (err) return console.error(err);
|
1627
1528
|
|
1628
|
-
|
1529
|
+
console.log("✅ AI Bot started!");
|
1629
1530
|
|
1630
|
-
|
1531
|
+
api.setOptions({
|
1532
|
+
listenEvents: true,
|
1533
|
+
selfListen: false
|
1534
|
+
});
|
1631
1535
|
|
1632
|
-
|
1536
|
+
api.listenMqtt((err, event) => {
|
1537
|
+
if (err) return console.error(err);
|
1633
1538
|
|
1634
|
-
|
1539
|
+
if (event.type === "message" && event.body) {
|
1540
|
+
const { body, threadID, messageID } = event;
|
1635
1541
|
|
1636
|
-
|
1542
|
+
// Ignore if doesn't start with "ai" prefix
|
1543
|
+
if (!body.toLowerCase().startsWith("ai ")) {
|
1544
|
+
return;
|
1545
|
+
}
|
1637
1546
|
|
1638
|
-
|
1639
|
-
|
1640
|
-
- `callback(err, messageInfo)`: (Optional) A callback called when sending the message is done (either with an error or with an confirmation object). `messageInfo` contains the `threadID` where the message was sent and a `messageID`, as well as the `timestamp` of the message.
|
1641
|
-
- `messageID`: (Optional) A string representing a message you want to reply.
|
1547
|
+
// Get message content (remove "ai " prefix)
|
1548
|
+
const userMessage = body.substring(3).trim();
|
1642
1549
|
|
1643
|
-
|
1550
|
+
// Show typing indicator
|
1551
|
+
api.sendTypingIndicator(threadID);
|
1644
1552
|
|
1645
|
-
|
1553
|
+
// Delay for more natural feel
|
1554
|
+
setTimeout(() => {
|
1555
|
+
const aiResponse = getAIResponse(userMessage, threadID);
|
1556
|
+
api.sendMessage(`🤖 ${aiResponse}`, threadID, messageID);
|
1557
|
+
}, 1500);
|
1558
|
+
}
|
1559
|
+
});
|
1560
|
+
}
|
1561
|
+
);
|
1562
|
+
```
|
1646
1563
|
|
1647
|
-
|
1648
|
-
- _Sticker:_ set a field `sticker` to the desired sticker ID.
|
1649
|
-
- _File or image:_ Set field `attachment` to a readable stream or an array of readable streams.
|
1650
|
-
- _URL:_ set a field `url` to the desired URL.
|
1651
|
-
- _Emoji:_ set field `emoji` to the desired emoji as a string and set field `emojiSize` with size of the emoji (`small`, `medium`, `large`)
|
1652
|
-
- _Mentions:_ set field `mentions` to an array of objects. Objects should have the `tag` field set to the text that should be highlighted in the mention. The object should have an `id` field, where the `id` is the user id of the person being mentioned. The instance of `tag` that is highlighted is determined through indexOf, an optional `fromIndex`
|
1653
|
-
can be passed in to specify the start index to start searching for the `tag` text
|
1654
|
-
in `body` (default=0). (See below for an example.)
|
1655
|
-
- _Location:_ set field `location` to an object with `latitude` and `longitude` fields. Optionally set field `current` of the `location` object to true to indicate the location is the user’s current location. Otherwise the location will be sent as a pinned location.
|
1564
|
+
---
|
1656
1565
|
|
1657
|
-
|
1566
|
+
### 4.4. Auto-Reply Bot with Keywords
|
1658
1567
|
|
1659
|
-
|
1568
|
+
```javascript
|
1569
|
+
const fs = require("fs");
|
1570
|
+
const login = require("@dongdev/fca-unofficial");
|
1571
|
+
|
1572
|
+
// Auto-reply dictionary
|
1573
|
+
const autoReplies = {
|
1574
|
+
"hello": "Hi there! How can I help you?",
|
1575
|
+
"hi": "Hello! What's up?",
|
1576
|
+
"bye": "Goodbye! See you later!",
|
1577
|
+
"thanks": "You're welcome! 😊",
|
1578
|
+
"help": "I'm here to assist! Just ask me anything.",
|
1579
|
+
"time": () => `Current time: ${new Date().toLocaleTimeString()}`,
|
1580
|
+
"date": () => `Today's date: ${new Date().toLocaleDateString()}`
|
1581
|
+
};
|
1660
1582
|
|
1661
|
-
|
1583
|
+
function getAutoReply(message) {
|
1584
|
+
const lowerMessage = message.toLowerCase().trim();
|
1662
1585
|
|
1663
|
-
|
1664
|
-
|
1665
|
-
|
1586
|
+
// Check for exact matches
|
1587
|
+
for (let keyword in autoReplies) {
|
1588
|
+
if (lowerMessage.includes(keyword)) {
|
1589
|
+
const reply = autoReplies[keyword];
|
1590
|
+
// If reply is function, execute it
|
1591
|
+
return typeof reply === 'function' ? reply() : reply;
|
1592
|
+
}
|
1593
|
+
}
|
1594
|
+
|
1595
|
+
return null; // No match found
|
1596
|
+
}
|
1666
1597
|
|
1667
1598
|
login(
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1599
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
1600
|
+
(err, api) => {
|
1601
|
+
if (err) return console.error(err);
|
1602
|
+
|
1603
|
+
console.log("✅ Auto-reply bot started!");
|
1604
|
+
|
1605
|
+
api.setOptions({
|
1606
|
+
listenEvents: true,
|
1607
|
+
selfListen: false
|
1608
|
+
});
|
1671
1609
|
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1610
|
+
api.listenMqtt((err, event) => {
|
1611
|
+
if (err) return console.error(err);
|
1612
|
+
|
1613
|
+
if (event.type === "message" && event.body) {
|
1614
|
+
const { body, threadID, messageID } = event;
|
1615
|
+
|
1616
|
+
const reply = getAutoReply(body);
|
1617
|
+
|
1618
|
+
if (reply) {
|
1619
|
+
api.sendMessage(reply, threadID, messageID);
|
1620
|
+
}
|
1621
|
+
}
|
1622
|
+
});
|
1623
|
+
}
|
1676
1624
|
);
|
1677
1625
|
```
|
1678
1626
|
|
1679
|
-
|
1627
|
+
---
|
1680
1628
|
|
1681
|
-
|
1629
|
+
### 4.5. Command Handler Bot
|
1630
|
+
|
1631
|
+
```javascript
|
1682
1632
|
const fs = require("fs");
|
1683
|
-
const login = require("fca-unofficial");
|
1633
|
+
const login = require("@dongdev/fca-unofficial");
|
1634
|
+
|
1635
|
+
// Command prefix
|
1636
|
+
const PREFIX = "/";
|
1637
|
+
|
1638
|
+
// Commands object
|
1639
|
+
const commands = {
|
1640
|
+
ping: {
|
1641
|
+
description: "Check bot latency",
|
1642
|
+
execute: (api, event) => {
|
1643
|
+
const start = Date.now();
|
1644
|
+
api.sendMessage("Pong! 🏓", event.threadID, (err) => {
|
1645
|
+
if (!err) {
|
1646
|
+
const latency = Date.now() - start;
|
1647
|
+
api.sendMessage(`Latency: ${latency}ms`, event.threadID);
|
1648
|
+
}
|
1649
|
+
});
|
1650
|
+
}
|
1651
|
+
},
|
1652
|
+
|
1653
|
+
userinfo: {
|
1654
|
+
description: "Get user information",
|
1655
|
+
execute: (api, event) => {
|
1656
|
+
api.getUserInfo(event.senderID, (err, userInfo) => {
|
1657
|
+
if (err) return api.sendMessage("Error getting user info!", event.threadID);
|
1658
|
+
|
1659
|
+
const user = userInfo[event.senderID];
|
1660
|
+
const info = `
|
1661
|
+
👤 USER INFO
|
1662
|
+
━━━━━━━━━━━━
|
1663
|
+
Name: ${user.name}
|
1664
|
+
Gender: ${user.gender}
|
1665
|
+
Profile: ${user.profileUrl}
|
1666
|
+
`.trim();
|
1667
|
+
|
1668
|
+
api.sendMessage(info, event.threadID);
|
1669
|
+
});
|
1670
|
+
}
|
1671
|
+
},
|
1672
|
+
|
1673
|
+
time: {
|
1674
|
+
description: "Get current time",
|
1675
|
+
execute: (api, event) => {
|
1676
|
+
const now = new Date();
|
1677
|
+
api.sendMessage(`🕐 Current time: ${now.toLocaleString()}`, event.threadID);
|
1678
|
+
}
|
1679
|
+
},
|
1680
|
+
|
1681
|
+
help: {
|
1682
|
+
description: "Show command list",
|
1683
|
+
execute: (api, event) => {
|
1684
|
+
let helpText = "📋 AVAILABLE COMMANDS\n━━━━━━━━━━━━━━━\n";
|
1685
|
+
|
1686
|
+
for (let cmd in commands) {
|
1687
|
+
helpText += `${PREFIX}${cmd} - ${commands[cmd].description}\n`;
|
1688
|
+
}
|
1689
|
+
|
1690
|
+
api.sendMessage(helpText, event.threadID);
|
1691
|
+
}
|
1692
|
+
}
|
1693
|
+
};
|
1684
1694
|
|
1685
1695
|
login(
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1696
|
+
{ appState: JSON.parse(fs.readFileSync("appstate.json", "utf8")) },
|
1697
|
+
(err, api) => {
|
1698
|
+
if (err) return console.error(err);
|
1699
|
+
|
1700
|
+
console.log("✅ Command handler bot started!");
|
1689
1701
|
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1702
|
+
api.setOptions({ listenEvents: true, selfListen: false });
|
1703
|
+
|
1704
|
+
api.listenMqtt((err, event) => {
|
1705
|
+
if (err) return console.error(err);
|
1706
|
+
|
1707
|
+
if (event.type === "message" && event.body) {
|
1708
|
+
const { body, threadID } = event;
|
1709
|
+
|
1710
|
+
// Check if message starts with prefix
|
1711
|
+
if (!body.startsWith(PREFIX)) return;
|
1712
|
+
|
1713
|
+
// Parse command
|
1714
|
+
const args = body.slice(PREFIX.length).trim().split(/ +/);
|
1715
|
+
const commandName = args.shift().toLowerCase();
|
1716
|
+
|
1717
|
+
// Execute command
|
1718
|
+
if (commands[commandName]) {
|
1719
|
+
try {
|
1720
|
+
commands[commandName].execute(api, event, args);
|
1721
|
+
} catch (error) {
|
1722
|
+
console.error("Command execution error:", error);
|
1723
|
+
api.sendMessage("Error executing command!", threadID);
|
1724
|
+
}
|
1725
|
+
} else {
|
1726
|
+
api.sendMessage(`Unknown command: ${commandName}\nUse ${PREFIX}help for command list`, threadID);
|
1727
|
+
}
|
1728
|
+
}
|
1729
|
+
});
|
1730
|
+
}
|
1698
1731
|
);
|
1699
1732
|
```
|
1700
1733
|
|
1701
|
-
|
1734
|
+
---
|
1735
|
+
|
1736
|
+
## 5. ERROR HANDLING & BEST PRACTICES
|
1702
1737
|
|
1703
|
-
|
1704
|
-
const login = require("fca-unofficial");
|
1738
|
+
### 5.1. Handle Checkpoint/Security Check
|
1705
1739
|
|
1706
|
-
|
1707
|
-
if (err) return console.error(err);
|
1740
|
+
When Facebook detects unusual activity, account may be checkpointed:
|
1708
1741
|
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1742
|
+
```javascript
|
1743
|
+
login(credentials, (err, api) => {
|
1744
|
+
if (err) {
|
1745
|
+
switch (err.error) {
|
1746
|
+
case "login-approval":
|
1747
|
+
console.log("❗ 2FA code required");
|
1748
|
+
// Handle 2FA
|
1749
|
+
break;
|
1750
|
+
|
1751
|
+
case "checkpoint":
|
1752
|
+
console.log("❌ Account checkpointed!");
|
1753
|
+
console.log("Please login via browser and verify");
|
1754
|
+
break;
|
1755
|
+
|
1756
|
+
default:
|
1757
|
+
console.error("Login error:", err);
|
1758
|
+
}
|
1759
|
+
return;
|
1726
1760
|
}
|
1727
|
-
});
|
1728
1761
|
});
|
1729
1762
|
```
|
1730
1763
|
|
1731
|
-
|
1764
|
+
---
|
1765
|
+
|
1766
|
+
### 5.2. Auto-save AppState
|
1767
|
+
|
1768
|
+
```javascript
|
1769
|
+
// Save AppState every 10 minutes
|
1770
|
+
setInterval(() => {
|
1771
|
+
try {
|
1772
|
+
const appState = api.getAppState();
|
1773
|
+
fs.writeFileSync("appstate.json", JSON.stringify(appState, null, 2));
|
1774
|
+
console.log("🔄 AppState updated");
|
1775
|
+
} catch (error) {
|
1776
|
+
console.error("Error saving AppState:", error);
|
1777
|
+
}
|
1778
|
+
}, 10 * 60 * 1000);
|
1779
|
+
```
|
1780
|
+
|
1781
|
+
---
|
1782
|
+
|
1783
|
+
### 5.3. Connection Error Handling
|
1732
1784
|
|
1733
|
-
```
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1785
|
+
```javascript
|
1786
|
+
api.listenMqtt((err, event) => {
|
1787
|
+
if (err) {
|
1788
|
+
console.error("Listen error:", err);
|
1789
|
+
|
1790
|
+
// Retry connection after 5 seconds
|
1791
|
+
setTimeout(() => {
|
1792
|
+
console.log("🔄 Reconnecting...");
|
1793
|
+
api.listenMqtt(arguments.callee);
|
1794
|
+
}, 5000);
|
1795
|
+
return;
|
1796
|
+
}
|
1797
|
+
|
1798
|
+
// Handle events normally
|
1742
1799
|
});
|
1743
1800
|
```
|
1744
1801
|
|
1745
1802
|
---
|
1746
1803
|
|
1747
|
-
|
1804
|
+
### 5.4. Rate Limiting (Avoid Spam)
|
1805
|
+
|
1806
|
+
```javascript
|
1807
|
+
const MESSAGE_COOLDOWN = {}; // Store last message time
|
1748
1808
|
|
1749
|
-
|
1809
|
+
function canSendMessage(threadID, cooldownTime = 1000) {
|
1810
|
+
const now = Date.now();
|
1811
|
+
const lastTime = MESSAGE_COOLDOWN[threadID] || 0;
|
1750
1812
|
|
1751
|
-
|
1813
|
+
if (now - lastTime < cooldownTime) {
|
1814
|
+
return false;
|
1815
|
+
}
|
1752
1816
|
|
1753
|
-
|
1817
|
+
MESSAGE_COOLDOWN[threadID] = now;
|
1818
|
+
return true;
|
1819
|
+
}
|
1754
1820
|
|
1755
|
-
|
1756
|
-
|
1821
|
+
api.listenMqtt((err, event) => {
|
1822
|
+
if (err) return console.error(err);
|
1823
|
+
|
1824
|
+
if (event.type === "message") {
|
1825
|
+
// Check cooldown
|
1826
|
+
if (!canSendMessage(event.threadID, 2000)) {
|
1827
|
+
console.log("⏱️ On cooldown...");
|
1828
|
+
return;
|
1829
|
+
}
|
1830
|
+
|
1831
|
+
// Handle message
|
1832
|
+
api.sendMessage("Response", event.threadID);
|
1833
|
+
}
|
1834
|
+
});
|
1835
|
+
```
|
1757
1836
|
|
1758
1837
|
---
|
1759
1838
|
|
1760
|
-
|
1839
|
+
### 5.5. Logging and Debug
|
1761
1840
|
|
1762
|
-
|
1841
|
+
```javascript
|
1842
|
+
// Enable detailed logging
|
1843
|
+
api.setOptions({
|
1844
|
+
logLevel: "verbose" // silent/error/warn/info/verbose
|
1845
|
+
});
|
1763
1846
|
|
1764
|
-
|
1847
|
+
// Custom logger
|
1848
|
+
function log(type, message, data = {}) {
|
1849
|
+
const timestamp = new Date().toISOString();
|
1850
|
+
console.log(`[${timestamp}] [${type.toUpperCase()}] ${message}`, data);
|
1851
|
+
}
|
1765
1852
|
|
1766
|
-
|
1853
|
+
api.listenMqtt((err, event) => {
|
1854
|
+
if (err) {
|
1855
|
+
log("error", "Listen error", err);
|
1856
|
+
return;
|
1857
|
+
}
|
1767
1858
|
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1859
|
+
log("info", "New event", {
|
1860
|
+
type: event.type,
|
1861
|
+
threadID: event.threadID
|
1862
|
+
});
|
1863
|
+
});
|
1864
|
+
```
|
1865
|
+
|
1866
|
+
---
|
1772
1867
|
|
1773
|
-
|
1868
|
+
### 5.6. Environment Variables for Credentials
|
1774
1869
|
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1870
|
+
```javascript
|
1871
|
+
require('dotenv').config();
|
1872
|
+
|
1873
|
+
const credentials = {
|
1874
|
+
email: process.env.FB_EMAIL,
|
1875
|
+
password: process.env.FB_PASSWORD
|
1876
|
+
};
|
1877
|
+
|
1878
|
+
// Or use AppState
|
1879
|
+
const credentials = {
|
1880
|
+
appState: JSON.parse(fs.readFileSync(process.env.APPSTATE_PATH, "utf8"))
|
1881
|
+
};
|
1882
|
+
```
|
1883
|
+
|
1884
|
+
**.env file:**
|
1885
|
+
```
|
1886
|
+
FB_EMAIL=your_email@example.com
|
1887
|
+
FB_PASSWORD=your_password
|
1888
|
+
APPSTATE_PATH=./appstate.json
|
1889
|
+
```
|
1786
1890
|
|
1787
1891
|
---
|
1788
1892
|
|
1789
|
-
|
1893
|
+
## 6. IMPORTANT NOTES
|
1790
1894
|
|
1791
|
-
###
|
1895
|
+
### ⚠️ Security Warnings
|
1792
1896
|
|
1793
|
-
|
1897
|
+
1. **Never share AppState**: The `appstate.json` file contains login information, never make it public
|
1898
|
+
2. **Use .gitignore**: Add `appstate.json` to `.gitignore`
|
1899
|
+
3. **Avoid hardcoding passwords**: Use environment variables or config files
|
1900
|
+
4. **Keep dependencies updated**: Regularly update the package
|
1794
1901
|
|
1795
|
-
|
1902
|
+
### 📝 Best Practices
|
1796
1903
|
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1801
|
-
|
1802
|
-
- `selfListen`: (Default `false`) Set this to `true` if you want your api
|
1803
|
-
to receive messages from its own account. This is to be used with
|
1804
|
-
caution, as it can result in loops (a simple echo bot will send messages
|
1805
|
-
forever).
|
1806
|
-
- `listenEvents`: (Default `false`) Will make [api.listen](#listen) also handle events (look at api.listen for more details).
|
1807
|
-
- `pageID`: (Default empty) Makes [api.listen](#listen) only receive messages through the page specified by that ID. Also makes [api.sendMessage](#sendMessage) send from the page.
|
1808
|
-
- `updatePresence`: (Default `false`) Will make [api.listen](#listen) also return `presence` ([api.listen](#presence) for more details).
|
1809
|
-
- `forceLogin`: (Default `false`) Will automatically approve of any recent logins and continue with the login process.
|
1810
|
-
- `userAgent`: (Default `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.3.18 (KHTML, like Gecko) Version/8.0.3 Safari/600.3.18`) The desired simulated User Agent. - `autoMarkDelivery`: (Default `true`) Will automatically mark new messages as delivered. See [api.markAsDelivered](#markAsDelivered). - `autoMarkRead`: (Default `false`) Will automatically mark new messages as read/seen. See [api.markAsRead](#markAsRead). - `proxy`: (Default empty) Set this to proxy server address to use proxy. Note: Only HTTP Proxies which support CONNECT method is supported. - `online`: (Default `true`) Set account's online state.
|
1904
|
+
1. **Use AppState instead of email/password**: Reduces checkpoint risk
|
1905
|
+
2. **Don't spam**: Avoid sending too many messages in short time
|
1906
|
+
3. **Complete error handling**: Always have callbacks to handle errors
|
1907
|
+
4. **Rate limiting**: Limit number of messages/requests
|
1908
|
+
5. **Log activities**: Keep logs for debugging
|
1811
1909
|
|
1812
|
-
|
1910
|
+
### 🚫 Avoid Getting Banned
|
1813
1911
|
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1912
|
+
- Don't login/logout repeatedly
|
1913
|
+
- Don't mass message strangers
|
1914
|
+
- Don't send spam links
|
1915
|
+
- Use real browser User-Agent
|
1916
|
+
- Limit requests per minute
|
1917
|
+
- Be a responsible Facebook citizen
|
1918
|
+
|
1919
|
+
---
|
1817
1920
|
|
1818
|
-
|
1921
|
+
## 7. TROUBLESHOOTING
|
1819
1922
|
|
1820
|
-
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1923
|
+
### Error: "Wrong username/password"
|
1924
|
+
- Check email and password
|
1925
|
+
- Try logging in manually via browser
|
1926
|
+
- Account may be checkpointed
|
1824
1927
|
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
});
|
1928
|
+
### Error: "Login approval needed"
|
1929
|
+
- Account has 2FA enabled
|
1930
|
+
- Provide 2FA verification code
|
1829
1931
|
|
1830
|
-
|
1831
|
-
|
1932
|
+
### Error: "Checkpoint required"
|
1933
|
+
- Login to Facebook via browser
|
1934
|
+
- Complete verification steps
|
1935
|
+
- Get new AppState after verification
|
1832
1936
|
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1937
|
+
### Bot not receiving messages
|
1938
|
+
- Check internet connection
|
1939
|
+
- Check logs for detailed errors
|
1940
|
+
- Try restarting bot
|
1941
|
+
- Update AppState
|
1942
|
+
|
1943
|
+
### Messages sending too slowly
|
1944
|
+
- Implement message queue
|
1945
|
+
- Use rate limiting
|
1946
|
+
- Check network latency
|
1947
|
+
|
1948
|
+
---
|
1949
|
+
|
1950
|
+
## 8. ADVANCED FEATURES
|
1951
|
+
|
1952
|
+
### 8.1. Message Queue System
|
1953
|
+
|
1954
|
+
```javascript
|
1955
|
+
class MessageQueue {
|
1956
|
+
constructor(api) {
|
1957
|
+
this.api = api;
|
1958
|
+
this.queue = [];
|
1959
|
+
this.processing = false;
|
1960
|
+
this.delay = 1000; // 1 second delay between messages
|
1961
|
+
}
|
1962
|
+
|
1963
|
+
add(message, threadID, messageID) {
|
1964
|
+
this.queue.push({ message, threadID, messageID });
|
1965
|
+
if (!this.processing) {
|
1966
|
+
this.process();
|
1967
|
+
}
|
1968
|
+
}
|
1969
|
+
|
1970
|
+
async process() {
|
1971
|
+
this.processing = true;
|
1972
|
+
|
1973
|
+
while (this.queue.length > 0) {
|
1974
|
+
const { message, threadID, messageID } = this.queue.shift();
|
1975
|
+
|
1976
|
+
await new Promise((resolve) => {
|
1977
|
+
this.api.sendMessage(message, threadID, messageID, (err) => {
|
1978
|
+
if (err) console.error("Send error:", err);
|
1979
|
+
setTimeout(resolve, this.delay);
|
1980
|
+
});
|
1981
|
+
});
|
1982
|
+
}
|
1983
|
+
|
1984
|
+
this.processing = false;
|
1985
|
+
}
|
1986
|
+
}
|
1987
|
+
|
1988
|
+
// Usage
|
1989
|
+
const messageQueue = new MessageQueue(api);
|
1990
|
+
|
1991
|
+
api.listenMqtt((err, event) => {
|
1992
|
+
if (err) return console.error(err);
|
1993
|
+
|
1994
|
+
if (event.type === "message") {
|
1995
|
+
messageQueue.add("Response", event.threadID, event.messageID);
|
1996
|
+
}
|
1997
|
+
});
|
1840
1998
|
```
|
1841
1999
|
|
1842
2000
|
---
|
1843
2001
|
|
1844
|
-
|
2002
|
+
### 8.2. Multi-Account Bot Manager
|
2003
|
+
|
2004
|
+
```javascript
|
2005
|
+
const fs = require("fs");
|
2006
|
+
const login = require("@dongdev/fca-unofficial");
|
2007
|
+
|
2008
|
+
class BotManager {
|
2009
|
+
constructor() {
|
2010
|
+
this.bots = new Map();
|
2011
|
+
}
|
2012
|
+
|
2013
|
+
async addBot(name, appStatePath) {
|
2014
|
+
return new Promise((resolve, reject) => {
|
2015
|
+
const credentials = {
|
2016
|
+
appState: JSON.parse(fs.readFileSync(appStatePath, "utf8"))
|
2017
|
+
};
|
2018
|
+
|
2019
|
+
login(credentials, (err, api) => {
|
2020
|
+
if (err) {
|
2021
|
+
reject(err);
|
2022
|
+
return;
|
2023
|
+
}
|
2024
|
+
|
2025
|
+
this.bots.set(name, api);
|
2026
|
+
console.log(`✅ Bot "${name}" connected`);
|
2027
|
+
resolve(api);
|
2028
|
+
});
|
2029
|
+
});
|
2030
|
+
}
|
2031
|
+
|
2032
|
+
getBot(name) {
|
2033
|
+
return this.bots.get(name);
|
2034
|
+
}
|
1845
2035
|
|
1846
|
-
|
2036
|
+
getAllBots() {
|
2037
|
+
return Array.from(this.bots.values());
|
2038
|
+
}
|
2039
|
+
}
|
1847
2040
|
|
1848
|
-
|
2041
|
+
// Usage
|
2042
|
+
const manager = new BotManager();
|
1849
2043
|
|
1850
|
-
|
2044
|
+
(async () => {
|
2045
|
+
await manager.addBot("bot1", "./appstate1.json");
|
2046
|
+
await manager.addBot("bot2", "./appstate2.json");
|
1851
2047
|
|
1852
|
-
|
2048
|
+
const bot1 = manager.getBot("bot1");
|
2049
|
+
const bot2 = manager.getBot("bot2");
|
1853
2050
|
|
1854
|
-
|
1855
|
-
|
1856
|
-
|
2051
|
+
// Use bots independently
|
2052
|
+
bot1.sendMessage("Message from Bot 1", threadID);
|
2053
|
+
bot2.sendMessage("Message from Bot 2", threadID);
|
2054
|
+
})();
|
2055
|
+
```
|
1857
2056
|
|
1858
2057
|
---
|
1859
2058
|
|
1860
|
-
|
2059
|
+
### 8.3. Database Integration (SQLite Example)
|
1861
2060
|
|
1862
|
-
|
2061
|
+
```javascript
|
2062
|
+
const sqlite3 = require('sqlite3').verbose();
|
2063
|
+
const db = new sqlite3.Database('./bot.db');
|
1863
2064
|
|
1864
|
-
|
2065
|
+
// Initialize database
|
2066
|
+
db.serialize(() => {
|
2067
|
+
db.run(`CREATE TABLE IF NOT EXISTS users (
|
2068
|
+
user_id TEXT PRIMARY KEY,
|
2069
|
+
username TEXT,
|
2070
|
+
message_count INTEGER DEFAULT 0,
|
2071
|
+
last_interaction TEXT
|
2072
|
+
)`);
|
2073
|
+
});
|
1865
2074
|
|
1866
|
-
|
2075
|
+
// Track user messages
|
2076
|
+
function trackUser(userID, username) {
|
2077
|
+
db.run(`
|
2078
|
+
INSERT INTO users (user_id, username, message_count, last_interaction)
|
2079
|
+
VALUES (?, ?, 1, datetime('now'))
|
2080
|
+
ON CONFLICT(user_id) DO UPDATE SET
|
2081
|
+
message_count = message_count + 1,
|
2082
|
+
last_interaction = datetime('now')
|
2083
|
+
`, [userID, username]);
|
2084
|
+
}
|
1867
2085
|
|
1868
|
-
|
2086
|
+
// Get user stats
|
2087
|
+
function getUserStats(userID, callback) {
|
2088
|
+
db.get('SELECT * FROM users WHERE user_id = ?', [userID], callback);
|
2089
|
+
}
|
1869
2090
|
|
1870
|
-
|
1871
|
-
|
2091
|
+
// Usage in bot
|
2092
|
+
api.listenMqtt((err, event) => {
|
2093
|
+
if (err) return console.error(err);
|
2094
|
+
|
2095
|
+
if (event.type === "message") {
|
2096
|
+
// Track user
|
2097
|
+
api.getUserInfo(event.senderID, (err, info) => {
|
2098
|
+
if (!err) {
|
2099
|
+
const username = info[event.senderID].name;
|
2100
|
+
trackUser(event.senderID, username);
|
2101
|
+
}
|
2102
|
+
});
|
2103
|
+
|
2104
|
+
// Stats command
|
2105
|
+
if (event.body === "/stats") {
|
2106
|
+
getUserStats(event.senderID, (err, row) => {
|
2107
|
+
if (err || !row) return;
|
2108
|
+
|
2109
|
+
const stats = `
|
2110
|
+
📊 YOUR STATS
|
2111
|
+
━━━━━━━━━━━━
|
2112
|
+
Messages: ${row.message_count}
|
2113
|
+
Last seen: ${row.last_interaction}
|
2114
|
+
`.trim();
|
2115
|
+
|
2116
|
+
api.sendMessage(stats, event.threadID);
|
2117
|
+
});
|
2118
|
+
}
|
2119
|
+
}
|
2120
|
+
});
|
2121
|
+
```
|
2122
|
+
|
2123
|
+
---
|
2124
|
+
|
2125
|
+
## 9. RESOURCES
|
2126
|
+
|
2127
|
+
- **GitHub Repository**: https://github.com/Donix-VN/fca-unofficial
|
2128
|
+
- **NPM Package**: @dongdev/fca-unofficial
|
2129
|
+
- **AppState Tool**: https://github.com/c3cbot/c3c-fbstate
|
2130
|
+
- **Facebook Developer Docs**: https://developers.facebook.com/docs/messenger-platform
|
1872
2131
|
|
1873
2132
|
---
|
2133
|
+
|
2134
|
+
## Conclusion
|
2135
|
+
|
2136
|
+
This is a comprehensive documentation for **@dongdev/fca-unofficial** API methods. This library is very powerful but should be used carefully to avoid violating Facebook's policies and getting your account banned.
|
2137
|
+
|
2138
|
+
**Happy bot coding! 🚀**
|