@cexy/hoonfca 1.0.6 → 2.0.1

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 (191) hide show
  1. package/LICENSE +3 -0
  2. package/examples/login-with-cookies.js +102 -0
  3. package/examples/verify.js +70 -0
  4. package/index.js +2 -8
  5. package/package.json +82 -61
  6. package/src/{api/action → apis}/addExternalModule.js +24 -25
  7. package/src/apis/addUserToGroup.js +108 -0
  8. package/src/apis/changeAdminStatus.js +148 -0
  9. package/src/apis/changeArchivedStatus.js +61 -0
  10. package/src/apis/changeAvatar.js +103 -0
  11. package/src/apis/changeBio.js +69 -0
  12. package/src/apis/changeBlockedStatus.js +54 -0
  13. package/src/apis/changeGroupImage.js +136 -0
  14. package/src/apis/changeThreadColor.js +116 -0
  15. package/src/apis/changeThreadEmoji.js +53 -0
  16. package/src/apis/comment.js +207 -0
  17. package/src/apis/createAITheme.js +129 -0
  18. package/src/apis/createNewGroup.js +79 -0
  19. package/src/apis/createPoll.js +73 -0
  20. package/src/apis/deleteMessage.js +44 -0
  21. package/src/apis/deleteThread.js +52 -0
  22. package/src/apis/e2ee.js +17 -0
  23. package/src/apis/editMessage.js +70 -0
  24. package/src/apis/emoji.js +124 -0
  25. package/src/apis/fetchThemeData.js +82 -0
  26. package/src/apis/follow.js +81 -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/getFriendsList.js +79 -0
  36. package/src/apis/getMessage.js +423 -0
  37. package/src/apis/getTheme.js +95 -0
  38. package/src/apis/getThemeInfo.js +116 -0
  39. package/src/apis/getThreadHistory.js +239 -0
  40. package/src/apis/getThreadInfo.js +267 -0
  41. package/src/apis/getThreadList.js +232 -0
  42. package/src/apis/getThreadPictures.js +58 -0
  43. package/src/apis/getUserID.js +117 -0
  44. package/src/apis/getUserInfo.js +513 -0
  45. package/src/{api/users → apis}/getUserInfoV2.js +146 -134
  46. package/src/apis/handleMessageRequest.js +50 -0
  47. package/src/apis/httpGet.js +63 -0
  48. package/src/apis/httpPost.js +89 -0
  49. package/src/apis/httpPostFormData.js +69 -0
  50. package/src/apis/listenMqtt.js +1236 -0
  51. package/src/apis/listenSpeed.js +179 -0
  52. package/src/apis/logout.js +87 -0
  53. package/src/apis/markAsDelivered.js +47 -0
  54. package/src/{api/messaging → apis}/markAsRead.js +99 -88
  55. package/src/apis/markAsReadAll.js +40 -0
  56. package/src/apis/markAsSeen.js +70 -0
  57. package/src/apis/mqttDeltaValue.js +278 -0
  58. package/src/apis/muteThread.js +45 -0
  59. package/src/apis/nickname.js +132 -0
  60. package/src/apis/notes.js +163 -0
  61. package/src/apis/pinMessage.js +150 -0
  62. package/src/apis/produceMetaTheme.js +180 -0
  63. package/src/apis/realtime.js +182 -0
  64. package/src/apis/removeUserFromGroup.js +117 -0
  65. package/src/apis/resolvePhotoUrl.js +58 -0
  66. package/src/apis/searchForThread.js +154 -0
  67. package/src/apis/sendMessage.js +354 -0
  68. package/src/apis/sendMessageMqtt.js +249 -0
  69. package/src/apis/sendTypingIndicator.js +91 -0
  70. package/src/apis/setMessageReaction.js +27 -0
  71. package/src/apis/setMessageReactionMqtt.js +61 -0
  72. package/src/apis/setThreadTheme.js +260 -0
  73. package/src/apis/setThreadThemeMqtt.js +94 -0
  74. package/src/apis/share.js +107 -0
  75. package/src/apis/shareContact.js +66 -0
  76. package/src/apis/stickers.js +257 -0
  77. package/src/apis/story.js +181 -0
  78. package/src/apis/theme.js +233 -0
  79. package/src/apis/unfriend.js +47 -0
  80. package/src/apis/unsendMessage.js +17 -0
  81. package/src/engine/client.js +92 -0
  82. package/src/engine/models/buildAPI.js +152 -0
  83. package/src/engine/models/loginHelper.js +519 -0
  84. package/src/engine/models/setOptions.js +88 -0
  85. package/src/security/e2ee.js +109 -0
  86. package/src/types/index.d.ts +498 -0
  87. package/src/utils/antiSuspension.js +506 -0
  88. package/src/utils/auth-helpers.js +149 -0
  89. package/src/utils/autoReLogin.js +336 -0
  90. package/src/utils/axios.js +436 -0
  91. package/src/utils/cache.js +54 -0
  92. package/src/utils/clients.js +282 -0
  93. package/src/utils/constants.js +410 -23
  94. package/src/utils/formatters/data/formatAttachment.js +370 -0
  95. package/src/utils/formatters/data/formatDelta.js +109 -0
  96. package/src/utils/formatters/index.js +159 -0
  97. package/src/utils/formatters/value/formatCookie.js +91 -0
  98. package/src/utils/formatters/value/formatDate.js +36 -0
  99. package/src/utils/formatters/value/formatID.js +16 -0
  100. package/src/utils/formatters.js +1373 -0
  101. package/src/utils/headers.js +214 -99
  102. package/src/utils/index.js +153 -0
  103. package/src/utils/monitoring.js +333 -0
  104. package/src/utils/rateLimiter.js +319 -0
  105. package/src/utils/tokenRefresh.js +657 -0
  106. package/src/utils/user-agents.js +238 -0
  107. package/src/utils/validation.js +157 -0
  108. package/CHANGELOG.md +0 -181
  109. package/DOCS.md +0 -2636
  110. package/LICENSE-MIT +0 -21
  111. package/README.md +0 -632
  112. package/func/checkUpdate.js +0 -231
  113. package/func/logger.js +0 -48
  114. package/index.d.ts +0 -746
  115. package/module/config.js +0 -67
  116. package/module/login.js +0 -154
  117. package/module/loginHelper.js +0 -1034
  118. package/module/options.js +0 -54
  119. package/src/api/action/changeAvatar.js +0 -137
  120. package/src/api/action/changeBio.js +0 -75
  121. package/src/api/action/enableAutoSaveAppState.js +0 -73
  122. package/src/api/action/getCurrentUserID.js +0 -7
  123. package/src/api/action/handleFriendRequest.js +0 -57
  124. package/src/api/action/logout.js +0 -76
  125. package/src/api/action/refreshFb_dtsg.js +0 -48
  126. package/src/api/action/setPostReaction.js +0 -106
  127. package/src/api/action/unfriend.js +0 -54
  128. package/src/api/http/httpGet.js +0 -46
  129. package/src/api/http/httpPost.js +0 -52
  130. package/src/api/http/postFormData.js +0 -47
  131. package/src/api/messaging/addUserToGroup.js +0 -68
  132. package/src/api/messaging/changeAdminStatus.js +0 -122
  133. package/src/api/messaging/changeArchivedStatus.js +0 -55
  134. package/src/api/messaging/changeBlockedStatus.js +0 -48
  135. package/src/api/messaging/changeGroupImage.js +0 -90
  136. package/src/api/messaging/changeNickname.js +0 -70
  137. package/src/api/messaging/changeThreadColor.js +0 -79
  138. package/src/api/messaging/changeThreadEmoji.js +0 -106
  139. package/src/api/messaging/createNewGroup.js +0 -88
  140. package/src/api/messaging/createPoll.js +0 -43
  141. package/src/api/messaging/createThemeAI.js +0 -98
  142. package/src/api/messaging/deleteMessage.js +0 -56
  143. package/src/api/messaging/deleteThread.js +0 -56
  144. package/src/api/messaging/editMessage.js +0 -68
  145. package/src/api/messaging/forwardAttachment.js +0 -51
  146. package/src/api/messaging/getEmojiUrl.js +0 -29
  147. package/src/api/messaging/getFriendsList.js +0 -82
  148. package/src/api/messaging/getMessage.js +0 -829
  149. package/src/api/messaging/getThemePictures.js +0 -62
  150. package/src/api/messaging/handleMessageRequest.js +0 -65
  151. package/src/api/messaging/markAsDelivered.js +0 -57
  152. package/src/api/messaging/markAsReadAll.js +0 -49
  153. package/src/api/messaging/markAsSeen.js +0 -61
  154. package/src/api/messaging/muteThread.js +0 -50
  155. package/src/api/messaging/removeUserFromGroup.js +0 -106
  156. package/src/api/messaging/resolvePhotoUrl.js +0 -43
  157. package/src/api/messaging/scheduler.js +0 -264
  158. package/src/api/messaging/searchForThread.js +0 -52
  159. package/src/api/messaging/sendMessage.js +0 -272
  160. package/src/api/messaging/sendTypingIndicator.js +0 -67
  161. package/src/api/messaging/setMessageReaction.js +0 -76
  162. package/src/api/messaging/setTitle.js +0 -119
  163. package/src/api/messaging/shareContact.js +0 -49
  164. package/src/api/messaging/threadColors.js +0 -128
  165. package/src/api/messaging/unsendMessage.js +0 -81
  166. package/src/api/messaging/uploadAttachment.js +0 -94
  167. package/src/api/socket/core/connectMqtt.js +0 -255
  168. package/src/api/socket/core/emitAuth.js +0 -106
  169. package/src/api/socket/core/getSeqID.js +0 -40
  170. package/src/api/socket/core/getTaskResponseData.js +0 -22
  171. package/src/api/socket/core/markDelivery.js +0 -12
  172. package/src/api/socket/core/parseDelta.js +0 -391
  173. package/src/api/socket/detail/buildStream.js +0 -208
  174. package/src/api/socket/detail/constants.js +0 -24
  175. package/src/api/socket/listenMqtt.js +0 -364
  176. package/src/api/socket/middleware/index.js +0 -216
  177. package/src/api/threads/getThreadHistory.js +0 -664
  178. package/src/api/threads/getThreadInfo.js +0 -438
  179. package/src/api/threads/getThreadList.js +0 -293
  180. package/src/api/threads/getThreadPictures.js +0 -78
  181. package/src/api/users/getUserID.js +0 -65
  182. package/src/api/users/getUserInfo.js +0 -327
  183. package/src/core/sendReqMqtt.js +0 -96
  184. package/src/database/models/index.js +0 -87
  185. package/src/database/models/thread.js +0 -45
  186. package/src/database/models/user.js +0 -46
  187. package/src/database/threadData.js +0 -98
  188. package/src/database/userData.js +0 -89
  189. package/src/utils/client.js +0 -320
  190. package/src/utils/format.js +0 -1115
  191. package/src/utils/request.js +0 -305
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 ^_^
@@ -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('nkxfca 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 CHANGED
@@ -1,8 +1,2 @@
1
- const login = require("./module/login");
2
-
3
- // CommonJS default export
4
- module.exports = login;
5
- // Support require('{ login }') named import pattern
6
- module.exports.login = login;
7
- // Support ESM default import interop
8
- module.exports.default = login;
1
+ "use strict";
2
+ module.exports = require('./src/engine/client');
package/package.json CHANGED
@@ -1,82 +1,103 @@
1
1
  {
2
2
  "name": "@cexy/hoonfca",
3
- "version": "1.0.6",
4
- "description": "Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically",
3
+ "version": "2.0.1",
4
+ "type": "commonjs",
5
+ "types": "src/types/index.d.ts",
6
+ "description": "Rakib FCA - Advanced Facebook Chat API",
5
7
  "main": "index.js",
6
- "types": "index.d.ts",
7
- "exports": {
8
- ".": {
9
- "require": "./index.js",
10
- "default": "./index.js",
11
- "types": "./index.d.ts"
12
- }
13
- },
14
- "scripts": {
15
- "test": "mocha",
16
- "lint": "eslint ."
17
- },
8
+ "files": [
9
+ "index.js",
10
+ "src/",
11
+ "examples/",
12
+ "LICENSE"
13
+ ],
18
14
  "repository": {
19
15
  "type": "git",
20
- "url": "git+https://github.com/Donix-VN/fca-unofficial.git"
16
+ "url": "git+https://github.com/bdrakib123/rakibfca.git"
17
+ },
18
+ "author": "Rakib Hasan",
19
+ "contributors": [
20
+ "Rakib Hasan"
21
+ ],
22
+ "license": "MIT",
23
+ "bugs": {
24
+ "url": "https://github.com/bdrakib123/rakibfca/issues"
21
25
  },
26
+ "homepage": "https://github.com/bdrakib123/rakibfca#readme",
22
27
  "keywords": [
23
28
  "facebook",
24
- "chat",
25
- "api",
26
29
  "messenger",
30
+ "chat",
27
31
  "bot",
28
- "unofficial",
32
+ "fca",
33
+ "mqtt",
34
+ "messaging",
35
+ "api",
29
36
  "automation",
30
- "facebook-api",
31
- "facebook-chat",
32
- "facebook-messenger",
33
- "chatbot",
34
- "nodejs",
35
- "fca"
37
+ "facebook-chat-api",
38
+ "rakibfca",
39
+ "rakib",
40
+ "anti-suspension",
41
+ "e2ee"
36
42
  ],
37
- "author": {
38
- "name": "DongDev",
39
- "url": "https://www.facebook.com/mdong.dev"
40
- },
41
- "contributors": [
42
- {
43
- "name": "DongDev",
44
- "url": "https://github.com/Donix-VN"
45
- }
46
- ],
47
- "license": "MIT",
48
- "bugs": {
49
- "url": "https://github.com/Donix-VN/fca-unofficial/issues"
50
- },
51
- "homepage": "https://github.com/Donix-VN/fca-unofficial#readme",
52
- "engines": {
53
- "node": ">=12.0.0"
54
- },
55
43
  "dependencies": {
56
- "axios": "latest",
57
- "axios-cookiejar-support": "^5.0.5",
44
+ "axios": "^1.9.0",
45
+ "axios-cookiejar-support": "^4.0.7",
58
46
  "bluebird": "^3.7.2",
59
- "chalk": "^4.1.2",
60
- "cheerio": "^1.0.0-rc.10",
47
+ "cheerio": "^1.0.0",
48
+ "deepdash": "^5.3.9",
61
49
  "duplexify": "^4.1.3",
62
- "gradient-string": "^2.0.2",
63
- "https-proxy-agent": "^4.0.0",
50
+ "form-data": "^4.0.4",
51
+ "https-proxy-agent": "^7.0.6",
52
+ "jsonpath-plus": "^10.3.0",
53
+ "lodash": "^4.17.21",
64
54
  "mqtt": "^4.3.8",
65
- "npmlog": "^1.2.0",
66
- "request": "^2.53.0",
67
- "sequelize": "^6.37.6",
68
- "sqlite3": "^5.1.7",
69
- "totp-generator": "^1.0.0",
70
- "ws": "^8.18.1"
55
+ "node-cron": "^3.0.3",
56
+ "npmlog": "^7.0.1",
57
+ "totp-generator": "^2.0.1",
58
+ "tough-cookie": "^5.1.2",
59
+ "undici": "^7.8.0",
60
+ "uuid": "^11.1.0",
61
+ "ws": "^8.18.2"
71
62
  },
72
63
  "devDependencies": {
73
- "eslint": "^8.50.0",
74
- "mocha": "^10.2.0"
64
+ "@types/node": "^22.15.17",
65
+ "eslint": "^9.26.0",
66
+ "mocha": "^11.3.0",
67
+ "prettier": "^3.5.3",
68
+ "ts-node": "^10.9.2",
69
+ "typescript": "^5.8.3"
70
+ },
71
+ "engines": {
72
+ "node": ">=22.0.0"
75
73
  },
76
- "optionalDependencies": {},
77
- "peerDependencies": {},
78
- "publishConfig": {
79
- "access": "public",
80
- "registry": "https://registry.npmjs.org/"
74
+ "scripts": {
75
+ "validate": "npm pack --dry-run",
76
+ "prepack": "echo 'Preparing package for npm...'",
77
+ "test": "echo 'No tests configured yet'",
78
+ "lint": "eslint src/",
79
+ "format": "prettier --write src/**/*.js"
80
+ },
81
+ "overrides": {
82
+ "undici": "^7.8.0",
83
+ "ws": "^8.18.2",
84
+ "tough-cookie": "^5.1.2",
85
+ "glob": "^11.0.2",
86
+ "prebuild-install": "^7.1.3",
87
+ "npmlog": "^7.0.1",
88
+ "are-we-there-yet": "^4.0.2",
89
+ "gauge": "^5.0.2",
90
+ "serialize-javascript": "^6.0.2",
91
+ "cacache": "^18.0.4",
92
+ "make-fetch-happen": "^13.0.3",
93
+ "@tootallnate/once": "^3.0.1",
94
+ "mocha": {
95
+ "serialize-javascript": "^6.0.2",
96
+ "debug": "^4.4.0",
97
+ "diff": "^7.0.0",
98
+ "js-yaml": "^4.1.0",
99
+ "minimatch": "^10.0.1",
100
+ "glob": "^11.0.2"
101
+ }
81
102
  }
82
103
  }
@@ -1,25 +1,24 @@
1
- "use strict";
2
-
3
- const { getType } = require("../../utils/format");
4
-
5
- module.exports = function(defaultFuncs, api, ctx) {
6
- return function addExternalModule(moduleObj) {
7
- if (getType(moduleObj) == "Object") {
8
- for (const apiName in moduleObj) {
9
- if (getType(moduleObj[apiName]) == "Function") {
10
- api[apiName] = moduleObj[apiName](defaultFuncs, api, ctx);
11
- } else {
12
- throw new Error(
13
- `Item "${apiName}" in moduleObj must be a function, not ${getType(
14
- moduleObj[apiName]
15
- )}!`
16
- );
17
- }
18
- }
19
- } else {
20
- throw new Error(
21
- `moduleObj must be an object, not ${getType(moduleObj)}!`
22
- );
23
- }
24
- };
25
- };
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
+ };