@lazyneoaz/nkxchat 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +3 -0
- package/README.md +199 -0
- package/examples/login-with-cookies.js +102 -0
- package/examples/verify.js +70 -0
- package/index.js +2 -0
- package/package.json +84 -0
- package/src/apis/addExternalModule.js +24 -0
- package/src/apis/addUserToGroup.js +108 -0
- package/src/apis/changeAdminStatus.js +148 -0
- package/src/apis/changeArchivedStatus.js +61 -0
- package/src/apis/changeAvatar.js +103 -0
- package/src/apis/changeBio.js +69 -0
- package/src/apis/changeBlockedStatus.js +54 -0
- package/src/apis/changeGroupImage.js +136 -0
- package/src/apis/changeThreadColor.js +116 -0
- package/src/apis/changeThreadEmoji.js +53 -0
- package/src/apis/comment.js +207 -0
- package/src/apis/createAITheme.js +129 -0
- package/src/apis/createNewGroup.js +79 -0
- package/src/apis/createPoll.js +73 -0
- package/src/apis/deleteMessage.js +44 -0
- package/src/apis/deleteThread.js +52 -0
- package/src/apis/editMessage.js +70 -0
- package/src/apis/emoji.js +124 -0
- package/src/apis/enableAutoSaveAppState.js +69 -0
- package/src/apis/fetchThemeData.js +113 -0
- package/src/apis/follow.js +81 -0
- package/src/apis/forwardAttachment.js +178 -0
- package/src/apis/forwardMessage.js +52 -0
- package/src/apis/friend.js +243 -0
- package/src/apis/gcmember.js +122 -0
- package/src/apis/gcname.js +123 -0
- package/src/apis/gcrule.js +119 -0
- package/src/apis/getAccess.js +111 -0
- package/src/apis/getBotInfo.js +88 -0
- package/src/apis/getBotInitialData.js +43 -0
- package/src/apis/getEmojiUrl.js +40 -0
- package/src/apis/getFriendsList.js +79 -0
- package/src/apis/getMessage.js +423 -0
- package/src/apis/getTheme.js +123 -0
- package/src/apis/getThemeInfo.js +116 -0
- package/src/apis/getThemePictures.js +87 -0
- package/src/apis/getThreadColors.js +119 -0
- package/src/apis/getThreadHistory.js +239 -0
- package/src/apis/getThreadInfo.js +267 -0
- package/src/apis/getThreadList.js +232 -0
- package/src/apis/getThreadPictures.js +58 -0
- package/src/apis/getUserID.js +117 -0
- package/src/apis/getUserInfo.js +513 -0
- package/src/apis/getUserInfoV2.js +146 -0
- package/src/apis/handleFriendRequest.js +66 -0
- package/src/apis/handleMessageRequest.js +50 -0
- package/src/apis/httpGet.js +63 -0
- package/src/apis/httpPost.js +89 -0
- package/src/apis/httpPostFormData.js +69 -0
- package/src/apis/listenMqtt.js +924 -0
- package/src/apis/listenSpeed.js +178 -0
- package/src/apis/logout.js +63 -0
- package/src/apis/markAsDelivered.js +47 -0
- package/src/apis/markAsRead.js +95 -0
- package/src/apis/markAsReadAll.js +40 -0
- package/src/apis/markAsSeen.js +70 -0
- package/src/apis/mqttDeltaValue.js +252 -0
- package/src/apis/muteThread.js +45 -0
- package/src/apis/nickname.js +132 -0
- package/src/apis/notes.js +163 -0
- package/src/apis/pinMessage.js +150 -0
- package/src/apis/produceMetaTheme.js +160 -0
- package/src/apis/realtime.js +182 -0
- package/src/apis/refreshFb_dtsg.js +94 -0
- package/src/apis/removeUserFromGroup.js +117 -0
- package/src/apis/resolvePhotoUrl.js +58 -0
- package/src/apis/searchForThread.js +154 -0
- package/src/apis/sendEffect.js +306 -0
- package/src/apis/sendMessage.js +353 -0
- package/src/apis/sendMessageMqtt.js +255 -0
- package/src/apis/sendTypingIndicator.js +40 -0
- package/src/apis/setMessageReaction.js +27 -0
- package/src/apis/setMessageReactionMqtt.js +61 -0
- package/src/apis/setPostReaction.js +118 -0
- package/src/apis/setThreadTheme.js +210 -0
- package/src/apis/setThreadThemeMqtt.js +94 -0
- package/src/apis/setTitle.js +26 -0
- package/src/apis/share.js +106 -0
- package/src/apis/shareContact.js +66 -0
- package/src/apis/stickers.js +257 -0
- package/src/apis/story.js +181 -0
- package/src/apis/theme.js +233 -0
- package/src/apis/unfriend.js +47 -0
- package/src/apis/unsendMessage.js +17 -0
- package/src/apis/uploadAttachment.js +87 -0
- package/src/database/appStateBackup.js +189 -0
- package/src/database/models/index.js +56 -0
- package/src/database/models/thread.js +31 -0
- package/src/database/models/user.js +32 -0
- package/src/database/threadData.js +101 -0
- package/src/database/userData.js +90 -0
- package/src/engine/client.js +92 -0
- package/src/engine/models/buildAPI.js +118 -0
- package/src/engine/models/loginHelper.js +492 -0
- package/src/engine/models/setOptions.js +88 -0
- package/src/types/index.d.ts +498 -0
- package/src/utils/antiSuspension.js +516 -0
- package/src/utils/auth-helpers.js +149 -0
- package/src/utils/autoReLogin.js +237 -0
- package/src/utils/axios.js +368 -0
- package/src/utils/cache.js +54 -0
- package/src/utils/clients.js +279 -0
- package/src/utils/constants.js +525 -0
- package/src/utils/formatters/data/formatAttachment.js +370 -0
- package/src/utils/formatters/data/formatDelta.js +109 -0
- package/src/utils/formatters/index.js +159 -0
- package/src/utils/formatters/value/formatCookie.js +91 -0
- package/src/utils/formatters/value/formatDate.js +36 -0
- package/src/utils/formatters/value/formatID.js +16 -0
- package/src/utils/formatters.js +1369 -0
- package/src/utils/headers.js +235 -0
- package/src/utils/index.js +152 -0
- package/src/utils/monitoring.js +333 -0
- package/src/utils/rateLimiter.js +251 -0
- package/src/utils/tokenRefresh.js +285 -0
- package/src/utils/user-agents.js +238 -0
- package/src/utils/validation.js +157 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# @lazyneoaz/nkxchat
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@lazyneoaz/nkxchat)
|
|
4
|
+
[](https://www.npmjs.com/package/@lazyneoaz/nkxchat)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
|
|
8
|
+
Advanced Facebook Chat API client for building Messenger bots — real-time messaging, thread management, MQTT, and session stability.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @lazyneoaz/nkxchat
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
const { login } = require('@lazyneoaz/nkxchat');
|
|
24
|
+
|
|
25
|
+
login({ appState: require('./appstate.json') }, (err, api) => {
|
|
26
|
+
if (err) return console.error(err);
|
|
27
|
+
|
|
28
|
+
api.listenMqtt((err, event) => {
|
|
29
|
+
if (err) return console.error(err);
|
|
30
|
+
if (event.type === 'message') {
|
|
31
|
+
api.sendMessage('Hello!', event.threadID);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Promise / async style
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const { login } = require('@lazyneoaz/nkxchat');
|
|
41
|
+
|
|
42
|
+
(async () => {
|
|
43
|
+
const api = await login({ appState: require('./appstate.json') });
|
|
44
|
+
|
|
45
|
+
api.listenMqtt((err, event) => {
|
|
46
|
+
if (event.type === 'message') {
|
|
47
|
+
api.sendMessage(`Echo: ${event.body}`, event.threadID);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
})();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Authentication
|
|
56
|
+
|
|
57
|
+
| Method | Description |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `appState` | Array of cookie objects from a browser session. **Recommended.** |
|
|
60
|
+
| `Cookie` | Raw cookie header string |
|
|
61
|
+
| `email` + `password` | Credential login (may trigger checkpoints — not recommended) |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
### Messages
|
|
68
|
+
| Method | Description |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `sendMessage(msg, threadID, [cb])` | Send text, attachments, stickers, mentions |
|
|
71
|
+
| `editMessage(text, messageID, [cb])` | Edit a sent message |
|
|
72
|
+
| `unsendMessage(messageID, [cb])` | Retract a message |
|
|
73
|
+
| `deleteMessage(messageIDs, [cb])` | Delete messages locally |
|
|
74
|
+
| `setMessageReaction(reaction, messageID, [cb])` | React to a message |
|
|
75
|
+
| `sendTypingIndicator(threadID, [cb])` | Show/hide typing indicator |
|
|
76
|
+
| `markAsRead(threadID, [cb])` | Mark thread as read |
|
|
77
|
+
| `markAsDelivered(threadID, messageID, [cb])` | Mark as delivered |
|
|
78
|
+
| `markAsSeen([cb])` | Mark all as seen |
|
|
79
|
+
| `markAsReadAll([cb])` | Mark all threads as read |
|
|
80
|
+
| `uploadAttachment(streams, [cb])` | Upload files, get attachment IDs |
|
|
81
|
+
| `forwardAttachment(ids, threadID, [cb])` | Forward attachments to a thread |
|
|
82
|
+
| `forwardMessage(messageID, threadIDs, [cb])` | Forward a message |
|
|
83
|
+
| `shareContact(text, userID, threadID, [cb])` | Share a contact card |
|
|
84
|
+
| `getMessage(messageID, [cb])` | Fetch a message by ID |
|
|
85
|
+
| `resolvePhotoUrl(fbid, [cb])` | Resolve full-resolution photo URL |
|
|
86
|
+
| `getEmojiUrl(char, size, [pixelRatio])` | Get CDN URL for an emoji image |
|
|
87
|
+
| `getThreadColors([query])` | List all Messenger color themes |
|
|
88
|
+
| `changeThreadColor(color, threadID, [cb])` | Change thread color |
|
|
89
|
+
| `changeThreadEmoji(emoji, threadID, [cb])` | Change thread emoji |
|
|
90
|
+
| `sendEffect(type, msg, threadID, [cb])` | Send a message effect (fire, confetti, etc.) |
|
|
91
|
+
| `pinMessage(messageID, threadID, [cb])` | Pin a message |
|
|
92
|
+
| `setPostReaction(postID, type, [cb])` | React to a Facebook post |
|
|
93
|
+
|
|
94
|
+
### Threads
|
|
95
|
+
| Method | Description |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `getThreadInfo(threadID, [cb])` | Get thread details |
|
|
98
|
+
| `getThreadList(limit, cursor, tags, [cb])` | List threads |
|
|
99
|
+
| `getThreadHistory(threadID, amount, timestamp, [cb])` | Get message history |
|
|
100
|
+
| `getThreadPictures(threadID, offset, limit, [cb])` | Get shared photos |
|
|
101
|
+
| `getThemePictures(themeID, [cb])` | Get theme asset images |
|
|
102
|
+
| `searchForThread(query, [cb])` | Search threads |
|
|
103
|
+
| `createNewGroup(name, userIDs, [cb])` | Create a group |
|
|
104
|
+
| `addUserToGroup(userID, threadID, [cb])` | Add user to group |
|
|
105
|
+
| `removeUserFromGroup(userID, threadID, [cb])` | Remove user from group |
|
|
106
|
+
| `changeAdminStatus(threadID, userID, adminStatus, [cb])` | Set admin status |
|
|
107
|
+
| `changeGroupImage(image, threadID, [cb])` | Update group photo |
|
|
108
|
+
| `changeNickname(nickname, threadID, participantID, [cb])` | Set nickname |
|
|
109
|
+
| `setTitle(title, threadID, [cb])` | Change group name |
|
|
110
|
+
| `gcname(name, threadID, [cb])` | Change group name (MQTT) |
|
|
111
|
+
| `createPoll(title, threadID, options, [cb])` | Create a poll |
|
|
112
|
+
| `createAITheme(prompt, threadID, [cb])` | Create AI-generated theme |
|
|
113
|
+
| `deleteThread(threadID, [cb])` | Delete a thread |
|
|
114
|
+
| `changeArchivedStatus(threadID, archived, [cb])` | Archive/unarchive |
|
|
115
|
+
| `muteThread(threadID, muteSeconds, [cb])` | Mute notifications |
|
|
116
|
+
| `handleMessageRequest(threadID, accept, [cb])` | Accept/decline message request |
|
|
117
|
+
| `getTheme(threadID, [cb])` | Get thread theme |
|
|
118
|
+
| `setThreadTheme(threadID, themeID, [cb])` | Set thread theme |
|
|
119
|
+
|
|
120
|
+
### Users
|
|
121
|
+
| Method | Description |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `getUserInfo(userIDs, [cb])` | Get user info by ID(s) |
|
|
124
|
+
| `getUserInfoV2(userID, [cb])` | Alternative user info endpoint |
|
|
125
|
+
| `getUserID(name, [cb])` | Resolve username to user ID |
|
|
126
|
+
| `getFriendsList([cb])` | Get friends list |
|
|
127
|
+
| `getCurrentUserID()` | Get the logged-in user's ID |
|
|
128
|
+
|
|
129
|
+
### Account
|
|
130
|
+
| Method | Description |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `changeAvatar(image, [cb])` | Update profile picture |
|
|
133
|
+
| `changeBio(bio, [cb])` | Update bio |
|
|
134
|
+
| `changeBlockedStatus(userID, block, [cb])` | Block/unblock a user |
|
|
135
|
+
| `handleFriendRequest(userID, accept, [cb])` | Accept/decline friend request |
|
|
136
|
+
| `unfriend(userID, [cb])` | Remove friend |
|
|
137
|
+
| `follow(userID, follow, [cb])` | Follow/unfollow a user |
|
|
138
|
+
| `refreshFb_dtsg([payload], [cb])` | Refresh session security token |
|
|
139
|
+
| `enableAutoSaveAppState([options])` | Auto-save cookies to file |
|
|
140
|
+
| `logout([cb])` | End session |
|
|
141
|
+
| `addExternalModule(name, module)` | Add an external module |
|
|
142
|
+
|
|
143
|
+
### HTTP Utilities
|
|
144
|
+
| Method | Description |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `httpGet(url, qs, [cb])` | Authenticated GET request |
|
|
147
|
+
| `httpPost(url, form, [cb])` | Authenticated POST request |
|
|
148
|
+
| `httpPostFormData(url, form, [cb])` | Multipart POST request |
|
|
149
|
+
|
|
150
|
+
### Realtime
|
|
151
|
+
| Method | Description |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `listenMqtt(cb)` | Start MQTT listener for real-time events |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Events
|
|
158
|
+
|
|
159
|
+
| Type | Description |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `message` | Incoming message |
|
|
162
|
+
| `message_reply` | Reply to a message |
|
|
163
|
+
| `message_reaction` | Reaction added/removed |
|
|
164
|
+
| `message_unsend` | Message retracted |
|
|
165
|
+
| `event` | Thread event (join, leave, name change, etc.) |
|
|
166
|
+
| `typ` | Typing indicator |
|
|
167
|
+
| `read` / `read_receipt` | Read receipt |
|
|
168
|
+
| `presence` | Online/offline status |
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Options
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
api.setOptions({
|
|
176
|
+
listenEvents: true, // receive thread events (joins, leaves, etc.)
|
|
177
|
+
selfListen: false, // receive own messages
|
|
178
|
+
autoMarkRead: false, // auto-mark incoming messages as read
|
|
179
|
+
autoReconnect: true, // reconnect MQTT on disconnect
|
|
180
|
+
online: false, // appear online
|
|
181
|
+
logLevel: 'info', // 'silent' | 'info' | 'warn' | 'error'
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Credits
|
|
188
|
+
|
|
189
|
+
Developed and maintained by **NeoKEX**
|
|
190
|
+
|
|
191
|
+
- GitHub: [https://github.com/lazyneoaz](https://github.com/lazyneoaz)
|
|
192
|
+
- Website: [https://neoaz.is-a.dev](https://neoaz.is-a.dev)
|
|
193
|
+
- npm: [https://www.npmjs.com/package/@lazyneoaz/nkxchat](https://www.npmjs.com/package/@lazyneoaz/nkxchat)
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example: Login with Cookie Array
|
|
6
|
+
*
|
|
7
|
+
* This demonstrates how to login to Facebook Chat API using a cookie array
|
|
8
|
+
* instead of email/password credentials.
|
|
9
|
+
*
|
|
10
|
+
* Cookie Format:
|
|
11
|
+
* - Array of objects with 'name' (or 'key') and 'value' properties
|
|
12
|
+
* - Extracted from browser cookies or previous session
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const login = require('../index.js');
|
|
16
|
+
|
|
17
|
+
// Method 1: Cookie Array with 'name' property
|
|
18
|
+
const cookieArray = [
|
|
19
|
+
{
|
|
20
|
+
name: 'c_user',
|
|
21
|
+
value: 'YOUR_USER_ID_HERE'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'xs',
|
|
25
|
+
value: 'YOUR_XS_TOKEN_HERE'
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'fr',
|
|
29
|
+
value: 'YOUR_FR_TOKEN_HERE'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'datr',
|
|
33
|
+
value: 'YOUR_DATR_TOKEN_HERE'
|
|
34
|
+
}
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
// Method 2: Cookie Array with 'key' property (alternative)
|
|
38
|
+
const cookieArrayAlt = [
|
|
39
|
+
{
|
|
40
|
+
key: 'c_user',
|
|
41
|
+
value: 'YOUR_USER_ID_HERE'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: 'xs',
|
|
45
|
+
value: 'YOUR_XS_TOKEN_HERE'
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// Method 3: Cookie String format (semicolon-separated)
|
|
50
|
+
const cookieString = 'c_user=YOUR_USER_ID_HERE; xs=YOUR_XS_TOKEN_HERE; fr=YOUR_FR_TOKEN_HERE; datr=YOUR_DATR_TOKEN_HERE';
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Login using cookie array
|
|
54
|
+
*/
|
|
55
|
+
async function loginWithCookies() {
|
|
56
|
+
try {
|
|
57
|
+
const api = await login.login({
|
|
58
|
+
appState: cookieArray // Pass the cookie array here
|
|
59
|
+
}, {
|
|
60
|
+
logging: true,
|
|
61
|
+
listenEvents: true,
|
|
62
|
+
autoMarkRead: true,
|
|
63
|
+
selfListen: false
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
console.log('✓ Successfully logged in using cookies!');
|
|
67
|
+
console.log('✓ User ID:', api.getCurrentUserID());
|
|
68
|
+
|
|
69
|
+
// Now you can use the API normally
|
|
70
|
+
// Example: Send a message
|
|
71
|
+
// api.sendMessage("Hello World!", threadID);
|
|
72
|
+
|
|
73
|
+
// Clean up
|
|
74
|
+
api.stopListening();
|
|
75
|
+
process.exit(0);
|
|
76
|
+
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('✗ Login failed:', error.message);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* How to extract cookies from your browser:
|
|
85
|
+
*
|
|
86
|
+
* 1. Open Facebook in your browser
|
|
87
|
+
* 2. Open Developer Tools (F12)
|
|
88
|
+
* 3. Go to Application → Cookies → facebook.com
|
|
89
|
+
* 4. Copy the critical cookies:
|
|
90
|
+
* - c_user: Your user ID
|
|
91
|
+
* - xs: Session token
|
|
92
|
+
* - fr: Fraud detection
|
|
93
|
+
* - datr: Device fingerprint
|
|
94
|
+
*
|
|
95
|
+
* 5. Replace the values in cookieArray above
|
|
96
|
+
* 6. Run: node examples/login-with-cookies.js
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
// Uncomment to run:
|
|
100
|
+
// loginWithCookies();
|
|
101
|
+
|
|
102
|
+
module.exports = { loginWithCookies, cookieArray };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Quick sanity check — verifies the library loads correctly and
|
|
6
|
+
* prints the anti-suspension configuration. Run with:
|
|
7
|
+
* node examples/verify.js
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fca = require('../index.js');
|
|
11
|
+
const { globalAntiSuspension } = require('../src/utils/antiSuspension');
|
|
12
|
+
const { globalRateLimiter } = require('../src/utils/rateLimiter');
|
|
13
|
+
|
|
14
|
+
console.log('dhoner-fca Library Verification');
|
|
15
|
+
console.log('================================\n');
|
|
16
|
+
|
|
17
|
+
console.log('Library entry point:', typeof fca.login === 'function' ? 'OK' : 'FAIL');
|
|
18
|
+
|
|
19
|
+
const config = globalAntiSuspension.getConfig();
|
|
20
|
+
console.log('\nAnti-Suspension Configuration:');
|
|
21
|
+
console.log(` Message Delay : ${config.messageDelayMs}ms`);
|
|
22
|
+
console.log(` Thread Delay : ${config.threadDelayMs}ms`);
|
|
23
|
+
console.log(` Max Login Tries : ${config.maxLoginAttempts}`);
|
|
24
|
+
console.log(` Login Cooldown : ${config.loginCooldownMs}ms`);
|
|
25
|
+
console.log(` Daily Msg Limit : ${config.dailyStats.maxDailyMessages}`);
|
|
26
|
+
console.log(` Hourly Msg Limit : ${config.hourlyStats.maxPerHour}`);
|
|
27
|
+
|
|
28
|
+
console.log('\nEnabled Features:');
|
|
29
|
+
Object.entries(config.features).forEach(([feature, enabled]) => {
|
|
30
|
+
console.log(` ${enabled ? '[x]' : '[ ]'} ${feature}`);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const activityPattern = globalAntiSuspension.getRealisticActivityPattern();
|
|
34
|
+
console.log('\nActivity Pattern:');
|
|
35
|
+
console.log(` Current activity : ${activityPattern.messageFrequency}`);
|
|
36
|
+
console.log(` Next action delay : ${activityPattern.nextActionDelayMs.toFixed(0)}ms`);
|
|
37
|
+
console.log(` Is active hours : ${activityPattern.isActiveHours}`);
|
|
38
|
+
|
|
39
|
+
console.log('\nCircuit Breaker:');
|
|
40
|
+
console.log(` Tripped : ${globalAntiSuspension.isCircuitBreakerTripped()}`);
|
|
41
|
+
console.log(` Signal count : ${globalAntiSuspension.suspensionCircuitBreaker.signalCount}`);
|
|
42
|
+
|
|
43
|
+
const rateLimiterStats = globalRateLimiter.getStats();
|
|
44
|
+
console.log('\nRate Limiter:');
|
|
45
|
+
console.log(` Max concurrent : ${rateLimiterStats.maxConcurrentRequests}`);
|
|
46
|
+
console.log(` Max per minute : ${rateLimiterStats.maxRequestsPerMinute}`);
|
|
47
|
+
console.log(` Requests (1 min) : ${rateLimiterStats.requestsInLastMinute}`);
|
|
48
|
+
|
|
49
|
+
// Test suspension signal detection
|
|
50
|
+
const testSignals = [
|
|
51
|
+
{ text: 'Everything is fine, message sent', expectSuspicion: false },
|
|
52
|
+
{ text: 'Your account has been suspended due to policy violation', expectSuspicion: true },
|
|
53
|
+
{ text: 'checkpoint required to verify identity', expectSuspicion: true },
|
|
54
|
+
{ text: 'Too many requests - rate limited', expectSuspicion: true },
|
|
55
|
+
{ text: 'Unusual activity detected on your account', expectSuspicion: true },
|
|
56
|
+
];
|
|
57
|
+
console.log('\nSuspension Signal Detection:');
|
|
58
|
+
testSignals.forEach(({ text, expectSuspicion }) => {
|
|
59
|
+
globalAntiSuspension.resetCircuitBreaker();
|
|
60
|
+
const detected = globalAntiSuspension.detectSuspensionSignal(text);
|
|
61
|
+
const passed = detected === expectSuspicion;
|
|
62
|
+
globalAntiSuspension.resetCircuitBreaker();
|
|
63
|
+
console.log(` ${passed ? '[x]' : '[!]'} "${text.substring(0, 40)}" → ${detected ? 'SUSPICIOUS' : 'CLEAN'}`);
|
|
64
|
+
});
|
|
65
|
+
globalAntiSuspension.resetCircuitBreaker();
|
|
66
|
+
|
|
67
|
+
console.log('\nAll checks passed. Library is ready to use.');
|
|
68
|
+
console.log('============================\n');
|
|
69
|
+
|
|
70
|
+
process.exit(0);
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lazyneoaz/nkxchat",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "commonjs",
|
|
5
|
+
"types": "src/types/index.d.ts",
|
|
6
|
+
"description": "Advanced Facebook Chat API client for building Messenger bots — real-time messaging, thread management, MQTT, and session stability.",
|
|
7
|
+
"main": "index.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"index.js",
|
|
10
|
+
"src/",
|
|
11
|
+
"examples/",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/lazyneoaz/nkxchat.git"
|
|
18
|
+
},
|
|
19
|
+
"author": "NeoKEX",
|
|
20
|
+
"contributors": [
|
|
21
|
+
"NeoKEX"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/lazyneoaz/nkxchat/issues"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://neoaz.is-a.dev",
|
|
28
|
+
"keywords": [
|
|
29
|
+
"facebook",
|
|
30
|
+
"messenger",
|
|
31
|
+
"chat",
|
|
32
|
+
"bot",
|
|
33
|
+
"fca",
|
|
34
|
+
"mqtt",
|
|
35
|
+
"messaging",
|
|
36
|
+
"api",
|
|
37
|
+
"automation",
|
|
38
|
+
"facebook-chat-api",
|
|
39
|
+
"nkxchat"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"axios": "^1.13.5",
|
|
43
|
+
"axios-cookiejar-support": "^4.0.7",
|
|
44
|
+
"bluebird": "^3.7.2",
|
|
45
|
+
"cheerio": "^1.0.0",
|
|
46
|
+
"cli-progress": "^3.12.0",
|
|
47
|
+
"deepdash": "^5.3.9",
|
|
48
|
+
"duplexify": "^4.1.3",
|
|
49
|
+
"form-data": "^4.0.4",
|
|
50
|
+
"gradient-string": "^3.0.0",
|
|
51
|
+
"https-proxy-agent": "^7.0.6",
|
|
52
|
+
"jsonpath-plus": "^10.3.0",
|
|
53
|
+
"lodash": "^4.17.21",
|
|
54
|
+
"mqtt": "^4.3.8",
|
|
55
|
+
"node-cron": "^3.0.3",
|
|
56
|
+
"ora": "^9.4.0",
|
|
57
|
+
"picocolors": "^1.1.1",
|
|
58
|
+
"sequelize": "^6.37.5",
|
|
59
|
+
"sqlite3": "^5.1.7",
|
|
60
|
+
"totp-generator": "^2.0.1",
|
|
61
|
+
"tough-cookie": "^4.1.4",
|
|
62
|
+
"undici": "^6.21.0",
|
|
63
|
+
"uuid": "^9.0.1",
|
|
64
|
+
"ws": "^8.18.0"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/form-data": "^2.2.1",
|
|
68
|
+
"@types/node": "^20.17.6",
|
|
69
|
+
"@types/tough-cookie": "^4.0.5",
|
|
70
|
+
"eslint": "^9.15.0",
|
|
71
|
+
"mocha": "^10.7.3",
|
|
72
|
+
"prettier": "^3.4.2",
|
|
73
|
+
"ts-node": "^10.9.2",
|
|
74
|
+
"typescript": "^5.7.2"
|
|
75
|
+
},
|
|
76
|
+
"engines": {
|
|
77
|
+
"node": ">=18.0.0"
|
|
78
|
+
},
|
|
79
|
+
"scripts": {
|
|
80
|
+
"validate": "npm pack --dry-run",
|
|
81
|
+
"prepack": "echo \"Preparing package for npm...\"",
|
|
82
|
+
"test": "echo \"No tests configured yet\""
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const utils = require('../utils');
|
|
3
|
+
|
|
4
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
5
|
+
return function addExternalModule(moduleObj) {
|
|
6
|
+
if (utils.getType(moduleObj) == "Object") {
|
|
7
|
+
for (const apiName in moduleObj) {
|
|
8
|
+
if (utils.getType(moduleObj[apiName]) == "Function") {
|
|
9
|
+
api[apiName] = moduleObj[apiName](defaultFuncs, api, ctx);
|
|
10
|
+
} else {
|
|
11
|
+
throw new Error(
|
|
12
|
+
`Item "${apiName}" in moduleObj must be a function, not ${utils.getType(
|
|
13
|
+
moduleObj[apiName],
|
|
14
|
+
)}!`,
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
} else {
|
|
19
|
+
throw new Error(
|
|
20
|
+
`moduleObj must be an object, not ${utils.getType(moduleObj)}!`,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
|
|
5
|
+
module.exports = (defaultFuncs, api, ctx) => {
|
|
6
|
+
return async function addUserToGroup(userID, threadID, callback) {
|
|
7
|
+
let resolveFunc = () => {};
|
|
8
|
+
let rejectFunc = () => {};
|
|
9
|
+
const returnPromise = new Promise((resolve, reject) => {
|
|
10
|
+
resolveFunc = resolve;
|
|
11
|
+
rejectFunc = reject;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
if (!callback) {
|
|
15
|
+
callback = (err, result) => {
|
|
16
|
+
if (err) return rejectFunc(err);
|
|
17
|
+
resolveFunc(result);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
if (!ctx.mqttClient) {
|
|
23
|
+
throw new Error("Not connected to MQTT. Please use listenMqtt first.");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (utils.getType(threadID) !== "Number" && utils.getType(threadID) !== "String") {
|
|
27
|
+
throw new Error("ThreadID should be of type Number or String");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (utils.getType(userID) !== "Array") {
|
|
31
|
+
userID = [userID];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const reqID = ++ctx.wsReqNumber;
|
|
35
|
+
const taskID = ++ctx.wsTaskNumber;
|
|
36
|
+
|
|
37
|
+
const payload = {
|
|
38
|
+
epoch_id: utils.generateOfflineThreadingID(),
|
|
39
|
+
tasks: [
|
|
40
|
+
{
|
|
41
|
+
failure_count: null,
|
|
42
|
+
label: "23",
|
|
43
|
+
payload: JSON.stringify({
|
|
44
|
+
thread_key: threadID,
|
|
45
|
+
contact_ids: userID,
|
|
46
|
+
sync_group: 1
|
|
47
|
+
}),
|
|
48
|
+
queue_name: threadID.toString(),
|
|
49
|
+
task_id: taskID
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
version_id: "24502707779384158"
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const form = JSON.stringify({
|
|
56
|
+
app_id: "772021112871879",
|
|
57
|
+
payload: JSON.stringify(payload),
|
|
58
|
+
request_id: reqID,
|
|
59
|
+
type: 3
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
let responseHandled = false;
|
|
63
|
+
const handleRes = (topic, message) => {
|
|
64
|
+
if (topic !== "/ls_resp" || responseHandled) return;
|
|
65
|
+
let jsonMsg;
|
|
66
|
+
try {
|
|
67
|
+
jsonMsg = JSON.parse(message.toString());
|
|
68
|
+
jsonMsg.payload = JSON.parse(jsonMsg.payload);
|
|
69
|
+
} catch {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (jsonMsg.request_id !== reqID) return;
|
|
73
|
+
responseHandled = true;
|
|
74
|
+
clearTimeout(timeout);
|
|
75
|
+
ctx.mqttClient.removeListener("message", handleRes);
|
|
76
|
+
callback(null, { success: true, response: jsonMsg.payload });
|
|
77
|
+
resolveFunc({ success: true, response: jsonMsg.payload });
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const timeout = setTimeout(() => {
|
|
81
|
+
if (!responseHandled) {
|
|
82
|
+
responseHandled = true;
|
|
83
|
+
ctx.mqttClient.removeListener("message", handleRes);
|
|
84
|
+
const err = new Error("MQTT request timeout");
|
|
85
|
+
callback(err);
|
|
86
|
+
rejectFunc(err);
|
|
87
|
+
}
|
|
88
|
+
}, 30000);
|
|
89
|
+
|
|
90
|
+
ctx.mqttClient.on("message", handleRes);
|
|
91
|
+
ctx.mqttClient.publish("/ls_req", form, { qos: 1, retain: false }, (err) => {
|
|
92
|
+
if (err && !responseHandled) {
|
|
93
|
+
responseHandled = true;
|
|
94
|
+
clearTimeout(timeout);
|
|
95
|
+
ctx.mqttClient.removeListener("message", handleRes);
|
|
96
|
+
callback(err);
|
|
97
|
+
rejectFunc(err);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
} catch (err) {
|
|
101
|
+
utils.error("addUserToGroup", err);
|
|
102
|
+
callback(err);
|
|
103
|
+
rejectFunc(err);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return returnPromise;
|
|
107
|
+
};
|
|
108
|
+
};
|