@lazyneoaz/metachat 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.
Files changed (122) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +199 -0
  3. package/index.js +2 -0
  4. package/package.json +86 -0
  5. package/src/apis/addExternalModule.js +24 -0
  6. package/src/apis/addUserToGroup.js +108 -0
  7. package/src/apis/changeAdminStatus.js +148 -0
  8. package/src/apis/changeArchivedStatus.js +61 -0
  9. package/src/apis/changeAvatar.js +103 -0
  10. package/src/apis/changeBio.js +69 -0
  11. package/src/apis/changeBlockedStatus.js +54 -0
  12. package/src/apis/changeGroupImage.js +136 -0
  13. package/src/apis/changeThreadColor.js +116 -0
  14. package/src/apis/changeThreadEmoji.js +53 -0
  15. package/src/apis/comment.js +207 -0
  16. package/src/apis/createAITheme.js +129 -0
  17. package/src/apis/createNewGroup.js +79 -0
  18. package/src/apis/createPoll.js +73 -0
  19. package/src/apis/deleteMessage.js +44 -0
  20. package/src/apis/deleteThread.js +52 -0
  21. package/src/apis/editMessage.js +70 -0
  22. package/src/apis/emoji.js +124 -0
  23. package/src/apis/enableAutoSaveAppState.js +69 -0
  24. package/src/apis/fetchThemeData.js +113 -0
  25. package/src/apis/follow.js +81 -0
  26. package/src/apis/forwardAttachment.js +195 -0
  27. package/src/apis/forwardMessage.js +52 -0
  28. package/src/apis/friend.js +243 -0
  29. package/src/apis/gcmember.js +122 -0
  30. package/src/apis/gcname.js +123 -0
  31. package/src/apis/gcrule.js +119 -0
  32. package/src/apis/getAccess.js +111 -0
  33. package/src/apis/getBotInfo.js +88 -0
  34. package/src/apis/getBotInitialData.js +43 -0
  35. package/src/apis/getEmojiUrl.js +40 -0
  36. package/src/apis/getFriendsList.js +79 -0
  37. package/src/apis/getMessage.js +423 -0
  38. package/src/apis/getTheme.js +123 -0
  39. package/src/apis/getThemeInfo.js +116 -0
  40. package/src/apis/getThemePictures.js +87 -0
  41. package/src/apis/getThreadColors.js +119 -0
  42. package/src/apis/getThreadHistory.js +239 -0
  43. package/src/apis/getThreadInfo.js +271 -0
  44. package/src/apis/getThreadList.js +236 -0
  45. package/src/apis/getThreadPictures.js +58 -0
  46. package/src/apis/getUserID.js +117 -0
  47. package/src/apis/getUserInfo.js +513 -0
  48. package/src/apis/getUserInfoV2.js +146 -0
  49. package/src/apis/handleFriendRequest.js +66 -0
  50. package/src/apis/handleMessageRequest.js +50 -0
  51. package/src/apis/httpGet.js +63 -0
  52. package/src/apis/httpPost.js +89 -0
  53. package/src/apis/httpPostFormData.js +69 -0
  54. package/src/apis/listenMqtt.js +1081 -0
  55. package/src/apis/listenSpeed.js +178 -0
  56. package/src/apis/logout.js +63 -0
  57. package/src/apis/markAsDelivered.js +47 -0
  58. package/src/apis/markAsRead.js +82 -0
  59. package/src/apis/markAsReadAll.js +40 -0
  60. package/src/apis/markAsSeen.js +70 -0
  61. package/src/apis/mqttDeltaValue.js +252 -0
  62. package/src/apis/muteThread.js +45 -0
  63. package/src/apis/nickname.js +132 -0
  64. package/src/apis/notes.js +163 -0
  65. package/src/apis/pinMessage.js +150 -0
  66. package/src/apis/produceMetaTheme.js +160 -0
  67. package/src/apis/realtime.js +182 -0
  68. package/src/apis/refreshFb_dtsg.js +94 -0
  69. package/src/apis/removeUserFromGroup.js +117 -0
  70. package/src/apis/resolvePhotoUrl.js +58 -0
  71. package/src/apis/scheduler.js +129 -0
  72. package/src/apis/searchForThread.js +154 -0
  73. package/src/apis/sendEffect.js +311 -0
  74. package/src/apis/sendMessage.js +341 -0
  75. package/src/apis/sendMessageMqtt.js +271 -0
  76. package/src/apis/sendTypingIndicator.js +74 -0
  77. package/src/apis/setMessageReaction.js +27 -0
  78. package/src/apis/setMessageReactionMqtt.js +61 -0
  79. package/src/apis/setPostReaction.js +118 -0
  80. package/src/apis/setThreadTheme.js +210 -0
  81. package/src/apis/setThreadThemeMqtt.js +94 -0
  82. package/src/apis/setTitle.js +26 -0
  83. package/src/apis/share.js +106 -0
  84. package/src/apis/shareContact.js +66 -0
  85. package/src/apis/stickers.js +257 -0
  86. package/src/apis/story.js +181 -0
  87. package/src/apis/theme.js +233 -0
  88. package/src/apis/unfriend.js +47 -0
  89. package/src/apis/unsendMessage.js +17 -0
  90. package/src/apis/uploadAttachment.js +87 -0
  91. package/src/database/appStateBackup.js +189 -0
  92. package/src/database/models/index.js +56 -0
  93. package/src/database/models/thread.js +31 -0
  94. package/src/database/models/user.js +32 -0
  95. package/src/database/threadData.js +101 -0
  96. package/src/database/userData.js +90 -0
  97. package/src/engine/client.js +92 -0
  98. package/src/engine/models/buildAPI.js +118 -0
  99. package/src/engine/models/loginHelper.js +492 -0
  100. package/src/engine/models/setOptions.js +88 -0
  101. package/src/types/index.d.ts +498 -0
  102. package/src/utils/antiSuspension.js +516 -0
  103. package/src/utils/auth-helpers.js +149 -0
  104. package/src/utils/autoReLogin.js +239 -0
  105. package/src/utils/axios.js +368 -0
  106. package/src/utils/cache.js +54 -0
  107. package/src/utils/clients.js +279 -0
  108. package/src/utils/constants.js +525 -0
  109. package/src/utils/formatters/data/formatAttachment.js +370 -0
  110. package/src/utils/formatters/data/formatDelta.js +109 -0
  111. package/src/utils/formatters/index.js +159 -0
  112. package/src/utils/formatters/value/formatCookie.js +91 -0
  113. package/src/utils/formatters/value/formatDate.js +36 -0
  114. package/src/utils/formatters/value/formatID.js +16 -0
  115. package/src/utils/formatters.js +1369 -0
  116. package/src/utils/headers.js +235 -0
  117. package/src/utils/index.js +153 -0
  118. package/src/utils/monitoring.js +333 -0
  119. package/src/utils/rateLimiter.js +251 -0
  120. package/src/utils/tokenRefresh.js +285 -0
  121. package/src/utils/user-agents.js +238 -0
  122. package/src/utils/validation.js +157 -0
package/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ All rights reserved to NeoKEX(github.com/NeoKEX)
2
+ ❌ PLEASE DO NOT STOLE MY SOURCE CODES AND CLAIM AS YOURS
3
+ Thanks for supporting ^_^
package/README.md ADDED
@@ -0,0 +1,199 @@
1
+ # @lazyneoaz/metachat
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@lazyneoaz/metachat.svg)](https://www.npmjs.com/package/@lazyneoaz/metachat)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@lazyneoaz/metachat.svg)](https://www.npmjs.com/package/@lazyneoaz/metachat)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![Node.js Version](https://img.shields.io/node/v/@lazyneoaz/metachat.svg)](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/metachat
16
+ ```
17
+
18
+ ---
19
+
20
+ ## Quick Start
21
+
22
+ ```js
23
+ const { login } = require('@lazyneoaz/metachat');
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/metachat');
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/metachat](https://www.npmjs.com/package/@lazyneoaz/metachat)
194
+
195
+ ---
196
+
197
+ ## License
198
+
199
+ MIT
package/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ module.exports = require('./src/engine/client');
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@lazyneoaz/metachat",
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
+ "LICENSE",
12
+ "README.md"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/lazyneoaz/metachat.git"
17
+ },
18
+ "author": "NeoKEX",
19
+ "contributors": [
20
+ "NeoKEX"
21
+ ],
22
+ "license": "MIT",
23
+ "bugs": {
24
+ "url": "https://github.com/lazyneoaz/metachat/issues"
25
+ },
26
+ "homepage": "https://neoaz.is-a.dev",
27
+ "keywords": [
28
+ "facebook",
29
+ "messenger",
30
+ "chat",
31
+ "bot",
32
+ "fca",
33
+ "mqtt",
34
+ "messaging",
35
+ "api",
36
+ "automation",
37
+ "facebook-chat-api",
38
+ "metachat"
39
+ ],
40
+ "dependencies": {
41
+ "axios": "^1.13.5",
42
+ "axios-cookiejar-support": "^4.0.7",
43
+ "bluebird": "^3.7.2",
44
+ "cheerio": "^1.0.0",
45
+ "cli-progress": "^3.12.0",
46
+ "deepdash": "^5.3.9",
47
+ "duplexify": "^4.1.3",
48
+ "form-data": "^4.0.4",
49
+ "gradient-string": "^3.0.0",
50
+ "https-proxy-agent": "^7.0.6",
51
+ "jsonpath-plus": "^10.3.0",
52
+ "lodash": "^4.17.21",
53
+ "mqtt": "^4.3.8",
54
+ "node-cron": "^3.0.3",
55
+ "ora": "^9.4.0",
56
+ "picocolors": "^1.1.1",
57
+ "sequelize": "^6.37.5",
58
+ "sqlite3": "^5.1.7",
59
+ "totp-generator": "^2.0.1",
60
+ "tough-cookie": "^4.1.4",
61
+ "undici": "^6.21.0",
62
+ "uuid": "^9.0.1",
63
+ "ws": "^8.18.0"
64
+ },
65
+ "devDependencies": {
66
+ "@types/form-data": "^2.2.1",
67
+ "@types/node": "^20.17.6",
68
+ "@types/tough-cookie": "^4.0.5",
69
+ "eslint": "^9.15.0",
70
+ "mocha": "^10.7.3",
71
+ "prettier": "^3.4.2",
72
+ "ts-node": "^10.9.2",
73
+ "typescript": "^5.7.2"
74
+ },
75
+ "engines": {
76
+ "node": ">=18.0.0"
77
+ },
78
+ "scripts": {
79
+ "validate": "npm pack --dry-run",
80
+ "prepack": "echo \"Preparing @lazyneoaz/metachat for npm...\"",
81
+ "test": "echo \"No tests configured yet\""
82
+ },
83
+ "publishConfig": {
84
+ "access": "public"
85
+ }
86
+ }
@@ -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
+ };
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+
3
+ const utils = require('../utils');
4
+
5
+ function generateOfflineThreadingID() {
6
+ return Date.now().toString() + Math.floor(Math.random() * 1000000).toString();
7
+ }
8
+
9
+ function getType(obj) {
10
+ return Object.prototype.toString.call(obj).slice(8, -1);
11
+ }
12
+
13
+ module.exports = function (defaultFuncs, api, ctx) {
14
+ return function changeAdminStatus(threadID, adminID, adminStatus, callback) {
15
+ let resolveFunc = function() {};
16
+ let rejectFunc = function() {};
17
+ const returnPromise = new Promise(function(resolve, reject) {
18
+ resolveFunc = resolve;
19
+ rejectFunc = reject;
20
+ });
21
+
22
+ if (!callback) {
23
+ callback = function(err, data) {
24
+ if (err) return rejectFunc(err);
25
+ resolveFunc(data);
26
+ };
27
+ }
28
+
29
+ if (getType(threadID) !== "String") {
30
+ return callback({ error: "changeAdminStatus: threadID must be a string" });
31
+ }
32
+ if (getType(adminID) !== "String" && getType(adminID) !== "Array") {
33
+ return callback({ error: "changeAdminStatus: adminID must be a string or an array" });
34
+ }
35
+ if (getType(adminStatus) !== "Boolean") {
36
+ return callback({ error: "changeAdminStatus: adminStatus must be true or false" });
37
+ }
38
+
39
+ if (ctx.mqttClient) {
40
+ const tasks = [];
41
+ const isAdmin = adminStatus ? 1 : 0;
42
+ const epochID = generateOfflineThreadingID();
43
+
44
+ if (getType(adminID) === "Array") {
45
+ adminID.forEach((id, index) => {
46
+ tasks.push({
47
+ failure_count: null,
48
+ label: "25",
49
+ payload: JSON.stringify({
50
+ thread_key: threadID,
51
+ contact_id: id,
52
+ is_admin: isAdmin
53
+ }),
54
+ queue_name: "admin_status",
55
+ task_id: index + 1
56
+ });
57
+ });
58
+ } else {
59
+ tasks.push({
60
+ failure_count: null,
61
+ label: "25",
62
+ payload: JSON.stringify({
63
+ thread_key: threadID,
64
+ contact_id: adminID,
65
+ is_admin: isAdmin
66
+ }),
67
+ queue_name: "admin_status",
68
+ task_id: 1
69
+ });
70
+ }
71
+
72
+ let count_req = 0;
73
+ const form = JSON.stringify({
74
+ app_id: "2220391788200892",
75
+ payload: JSON.stringify({
76
+ epoch_id: epochID,
77
+ tasks: tasks,
78
+ version_id: "8798795233522156"
79
+ }),
80
+ request_id: ++count_req,
81
+ type: 3
82
+ });
83
+
84
+ ctx.mqttClient.publish("/ls_req", form, {}, (err, _packet) => {
85
+ if (err) {
86
+ utils.error("changeAdminStatus (MQTT)", err);
87
+ return callback(err);
88
+ } else {
89
+ utils.log("Admin status changed successfully via MQTT");
90
+ return callback(null, { success: true });
91
+ }
92
+ });
93
+ } else {
94
+ utils.warn("MQTT client not available, using HTTP fallback for changeAdminStatus");
95
+ const tasks = [];
96
+ const epochID = generateOfflineThreadingID();
97
+
98
+ if (getType(adminID) === "Array") {
99
+ adminID.forEach((id, index) => {
100
+ tasks.push({
101
+ label: '25',
102
+ payload: JSON.stringify({ thread_key: threadID, contact_id: id, is_admin: adminStatus }),
103
+ queue_name: 'admin_status',
104
+ task_id: index + 1,
105
+ failure_count: null
106
+ });
107
+ });
108
+ } else {
109
+ tasks.push({
110
+ label: '25',
111
+ payload: JSON.stringify({ thread_key: threadID, contact_id: adminID, is_admin: adminStatus }),
112
+ queue_name: 'admin_status',
113
+ task_id: 1,
114
+ failure_count: null
115
+ });
116
+ }
117
+
118
+ const form = {
119
+ fb_dtsg: ctx.fb_dtsg,
120
+ request_id: 1,
121
+ type: 3,
122
+ payload: {
123
+ version_id: '3816854585040595',
124
+ tasks: tasks,
125
+ epoch_id: epochID,
126
+ data_trace_id: null
127
+ },
128
+ app_id: '772021112871879'
129
+ };
130
+
131
+ form.payload = JSON.stringify(form.payload);
132
+
133
+ defaultFuncs
134
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
135
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
136
+ .then(() => {
137
+ utils.log("Admin status changed successfully via HTTP");
138
+ callback(null, { success: true });
139
+ })
140
+ .catch(err => {
141
+ utils.error("changeAdminStatus (HTTP)", err);
142
+ callback(err);
143
+ });
144
+ }
145
+
146
+ return returnPromise;
147
+ };
148
+ };
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+
3
+ const utils = require('../utils');
4
+
5
+ module.exports = (defaultFuncs, api, ctx) => {
6
+ return async function changeArchivedStatus(threadIDs, archive, 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 (utils.getType(archive) === "Function") {
23
+ callback = archive;
24
+ archive = true;
25
+ }
26
+
27
+ if (utils.getType(archive) !== "Boolean") {
28
+ throw new Error("archive parameter must be a boolean");
29
+ }
30
+
31
+ if (!Array.isArray(threadIDs)) {
32
+ threadIDs = [threadIDs];
33
+ }
34
+
35
+ const form = {
36
+ should_archive: archive
37
+ };
38
+
39
+ threadIDs.forEach(id => {
40
+ form[`thread_fbids[${id}]`] = true;
41
+ });
42
+
43
+ const res = await defaultFuncs.post(
44
+ "https://www.facebook.com/ajax/mercury/change_archived_status.php",
45
+ ctx.jar,
46
+ form
47
+ ).then(utils.parseAndCheckLogin(ctx, defaultFuncs));
48
+
49
+ if (res && res.error) {
50
+ throw res;
51
+ }
52
+
53
+ callback(null, { success: true });
54
+ } catch (err) {
55
+ utils.error("changeArchivedStatus", err);
56
+ callback(err);
57
+ }
58
+
59
+ return returnPromise;
60
+ };
61
+ };