@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.
Files changed (123) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +199 -0
  3. package/examples/login-with-cookies.js +102 -0
  4. package/examples/verify.js +70 -0
  5. package/index.js +2 -0
  6. package/package.json +84 -0
  7. package/src/apis/addExternalModule.js +24 -0
  8. package/src/apis/addUserToGroup.js +108 -0
  9. package/src/apis/changeAdminStatus.js +148 -0
  10. package/src/apis/changeArchivedStatus.js +61 -0
  11. package/src/apis/changeAvatar.js +103 -0
  12. package/src/apis/changeBio.js +69 -0
  13. package/src/apis/changeBlockedStatus.js +54 -0
  14. package/src/apis/changeGroupImage.js +136 -0
  15. package/src/apis/changeThreadColor.js +116 -0
  16. package/src/apis/changeThreadEmoji.js +53 -0
  17. package/src/apis/comment.js +207 -0
  18. package/src/apis/createAITheme.js +129 -0
  19. package/src/apis/createNewGroup.js +79 -0
  20. package/src/apis/createPoll.js +73 -0
  21. package/src/apis/deleteMessage.js +44 -0
  22. package/src/apis/deleteThread.js +52 -0
  23. package/src/apis/editMessage.js +70 -0
  24. package/src/apis/emoji.js +124 -0
  25. package/src/apis/enableAutoSaveAppState.js +69 -0
  26. package/src/apis/fetchThemeData.js +113 -0
  27. package/src/apis/follow.js +81 -0
  28. package/src/apis/forwardAttachment.js +178 -0
  29. package/src/apis/forwardMessage.js +52 -0
  30. package/src/apis/friend.js +243 -0
  31. package/src/apis/gcmember.js +122 -0
  32. package/src/apis/gcname.js +123 -0
  33. package/src/apis/gcrule.js +119 -0
  34. package/src/apis/getAccess.js +111 -0
  35. package/src/apis/getBotInfo.js +88 -0
  36. package/src/apis/getBotInitialData.js +43 -0
  37. package/src/apis/getEmojiUrl.js +40 -0
  38. package/src/apis/getFriendsList.js +79 -0
  39. package/src/apis/getMessage.js +423 -0
  40. package/src/apis/getTheme.js +123 -0
  41. package/src/apis/getThemeInfo.js +116 -0
  42. package/src/apis/getThemePictures.js +87 -0
  43. package/src/apis/getThreadColors.js +119 -0
  44. package/src/apis/getThreadHistory.js +239 -0
  45. package/src/apis/getThreadInfo.js +267 -0
  46. package/src/apis/getThreadList.js +232 -0
  47. package/src/apis/getThreadPictures.js +58 -0
  48. package/src/apis/getUserID.js +117 -0
  49. package/src/apis/getUserInfo.js +513 -0
  50. package/src/apis/getUserInfoV2.js +146 -0
  51. package/src/apis/handleFriendRequest.js +66 -0
  52. package/src/apis/handleMessageRequest.js +50 -0
  53. package/src/apis/httpGet.js +63 -0
  54. package/src/apis/httpPost.js +89 -0
  55. package/src/apis/httpPostFormData.js +69 -0
  56. package/src/apis/listenMqtt.js +924 -0
  57. package/src/apis/listenSpeed.js +178 -0
  58. package/src/apis/logout.js +63 -0
  59. package/src/apis/markAsDelivered.js +47 -0
  60. package/src/apis/markAsRead.js +95 -0
  61. package/src/apis/markAsReadAll.js +40 -0
  62. package/src/apis/markAsSeen.js +70 -0
  63. package/src/apis/mqttDeltaValue.js +252 -0
  64. package/src/apis/muteThread.js +45 -0
  65. package/src/apis/nickname.js +132 -0
  66. package/src/apis/notes.js +163 -0
  67. package/src/apis/pinMessage.js +150 -0
  68. package/src/apis/produceMetaTheme.js +160 -0
  69. package/src/apis/realtime.js +182 -0
  70. package/src/apis/refreshFb_dtsg.js +94 -0
  71. package/src/apis/removeUserFromGroup.js +117 -0
  72. package/src/apis/resolvePhotoUrl.js +58 -0
  73. package/src/apis/searchForThread.js +154 -0
  74. package/src/apis/sendEffect.js +306 -0
  75. package/src/apis/sendMessage.js +353 -0
  76. package/src/apis/sendMessageMqtt.js +255 -0
  77. package/src/apis/sendTypingIndicator.js +40 -0
  78. package/src/apis/setMessageReaction.js +27 -0
  79. package/src/apis/setMessageReactionMqtt.js +61 -0
  80. package/src/apis/setPostReaction.js +118 -0
  81. package/src/apis/setThreadTheme.js +210 -0
  82. package/src/apis/setThreadThemeMqtt.js +94 -0
  83. package/src/apis/setTitle.js +26 -0
  84. package/src/apis/share.js +106 -0
  85. package/src/apis/shareContact.js +66 -0
  86. package/src/apis/stickers.js +257 -0
  87. package/src/apis/story.js +181 -0
  88. package/src/apis/theme.js +233 -0
  89. package/src/apis/unfriend.js +47 -0
  90. package/src/apis/unsendMessage.js +17 -0
  91. package/src/apis/uploadAttachment.js +87 -0
  92. package/src/database/appStateBackup.js +189 -0
  93. package/src/database/models/index.js +56 -0
  94. package/src/database/models/thread.js +31 -0
  95. package/src/database/models/user.js +32 -0
  96. package/src/database/threadData.js +101 -0
  97. package/src/database/userData.js +90 -0
  98. package/src/engine/client.js +92 -0
  99. package/src/engine/models/buildAPI.js +118 -0
  100. package/src/engine/models/loginHelper.js +492 -0
  101. package/src/engine/models/setOptions.js +88 -0
  102. package/src/types/index.d.ts +498 -0
  103. package/src/utils/antiSuspension.js +516 -0
  104. package/src/utils/auth-helpers.js +149 -0
  105. package/src/utils/autoReLogin.js +237 -0
  106. package/src/utils/axios.js +368 -0
  107. package/src/utils/cache.js +54 -0
  108. package/src/utils/clients.js +279 -0
  109. package/src/utils/constants.js +525 -0
  110. package/src/utils/formatters/data/formatAttachment.js +370 -0
  111. package/src/utils/formatters/data/formatDelta.js +109 -0
  112. package/src/utils/formatters/index.js +159 -0
  113. package/src/utils/formatters/value/formatCookie.js +91 -0
  114. package/src/utils/formatters/value/formatDate.js +36 -0
  115. package/src/utils/formatters/value/formatID.js +16 -0
  116. package/src/utils/formatters.js +1369 -0
  117. package/src/utils/headers.js +235 -0
  118. package/src/utils/index.js +152 -0
  119. package/src/utils/monitoring.js +333 -0
  120. package/src/utils/rateLimiter.js +251 -0
  121. package/src/utils/tokenRefresh.js +285 -0
  122. package/src/utils/user-agents.js +238 -0
  123. package/src/utils/validation.js +157 -0
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+
3
+ const { makeParsable, log, warn } = require("./constants");
4
+ const { globalRateLimiter, configureRateLimiter } = require("./rateLimiter");
5
+
6
+ /**
7
+ * Formats a cookie array into a string for use in a cookie jar.
8
+ * @param {Array<string>} arr - An array containing cookie parts.
9
+ * @param {string} url - The base URL for the cookie domain.
10
+ * @returns {string} The formatted cookie string.
11
+ */
12
+ function formatCookie(arr, url) {
13
+ return arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + url + ".com";
14
+ }
15
+
16
+ /**
17
+ * Parses a response from Facebook, checks for login status, and handles retries.
18
+ * @param {Object} ctx - The application context.
19
+ * @param {Object} http - The HTTP request functions.
20
+ * @param {number} [retryCount=0] - The current retry count for the request.
21
+ * @returns {function(data: Object): Promise<Object>} A function that processes the response data.
22
+ */
23
+ function parseAndCheckLogin(ctx, http, retryCount = 0) {
24
+ const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
25
+
26
+ return async (data) => {
27
+ if (data.statusCode === 401) {
28
+ const err = new Error("Session expired - Authentication required");
29
+ err.error = 401;
30
+ err.errorCode = 401;
31
+ err.errorType = "AUTHENTICATION_REQUIRED";
32
+ err.requiresReLogin = true;
33
+ warn("Session Status", "Session expired. Re-login required.");
34
+ throw err;
35
+ }
36
+
37
+ if (data.statusCode >= 500 && data.statusCode < 600) {
38
+ if (retryCount >= 5) {
39
+ const err = new Error("Request retry failed. Check the `res` and `statusCode` property on this error.");
40
+ err.statusCode = data.statusCode;
41
+ err.res = data.body;
42
+ err.error = "Request retry failed. Check the `res` and `statusCode` property on this error.";
43
+ throw err;
44
+ }
45
+
46
+ retryCount++;
47
+ const retryTime = Math.floor(Math.random() * 5000);
48
+ const url = data.request.uri.protocol + "//" + data.request.uri.hostname + data.request.uri.pathname;
49
+
50
+ await delay(retryTime);
51
+
52
+ if (data.request.headers["content-type"].split(";")[0] === "multipart/form-data") {
53
+ const newData = await http.postFormData(
54
+ url,
55
+ ctx.jar,
56
+ data.request.formData,
57
+ data.request.qs,
58
+ ctx.globalOptions,
59
+ ctx
60
+ );
61
+ return await parseAndCheckLogin(ctx, http, retryCount)(newData);
62
+ } else {
63
+ const newData = await http.post(
64
+ url,
65
+ ctx.jar,
66
+ data.request.form,
67
+ ctx.globalOptions,
68
+ ctx
69
+ );
70
+ return await parseAndCheckLogin(ctx, http, retryCount)(newData);
71
+ }
72
+ }
73
+
74
+ if (data.statusCode === 404) return;
75
+
76
+ if (data.statusCode !== 200) {
77
+ throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
78
+ }
79
+
80
+ let res = null;
81
+
82
+ if (typeof data.body === 'object' && data.body !== null) {
83
+ res = data.body;
84
+ } else if (typeof data.body === 'string') {
85
+ try {
86
+ res = JSON.parse(makeParsable(data.body));
87
+ } catch (e) {
88
+ const err = new Error("JSON.parse error. Check the `detail` property on this error.");
89
+ err.error = "JSON.parse error. Check the `detail` property on this error.";
90
+ err.detail = e;
91
+ err.res = data.body;
92
+ throw err;
93
+ }
94
+ } else {
95
+ throw new Error("Unknown response body type: " + typeof data.body);
96
+ }
97
+
98
+ if (res.redirect && data.request.method === "GET") {
99
+ const redirectRes = await http.get(res.redirect, ctx.jar);
100
+ return await parseAndCheckLogin(ctx, http)(redirectRes);
101
+ }
102
+
103
+ if (res.jsmods && res.jsmods.require && Array.isArray(res.jsmods.require[0]) && res.jsmods.require[0][0] === "Cookie") {
104
+ res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
105
+ const requireCookie = res.jsmods.require[0][3];
106
+ ctx.jar.setCookie(formatCookie(requireCookie, "facebook"), "https://www.facebook.com");
107
+ ctx.jar.setCookie(formatCookie(requireCookie, "messenger"), "https://www.messenger.com");
108
+ }
109
+
110
+ if (res.jsmods && Array.isArray(res.jsmods.require)) {
111
+ const arr = res.jsmods.require;
112
+ for (const i in arr) {
113
+ if (arr[i][0] === "DTSG" && arr[i][1] === "setToken") {
114
+ ctx.fb_dtsg = arr[i][3][0];
115
+ ctx.ttstamp = "2";
116
+ for (let j = 0; j < ctx.fb_dtsg.length; j++) {
117
+ ctx.ttstamp += ctx.fb_dtsg.charCodeAt(j);
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ const SESSION_EXPIRY_CODES = {
124
+ 1357046: "Session token expired - Re-authentication required",
125
+ 1357045: "Invalid session token - Re-login needed",
126
+ 458: "Session expired - User not logged in"
127
+ };
128
+
129
+ if (res.error && SESSION_EXPIRY_CODES[res.error]) {
130
+ const err = new Error(SESSION_EXPIRY_CODES[res.error]);
131
+ err.error = res.error;
132
+ err.errorCode = res.error;
133
+ err.errorType = "SESSION_EXPIRED";
134
+ err.requiresReLogin = true;
135
+ warn("Session Status", `${SESSION_EXPIRY_CODES[res.error]} (Code: ${res.error})`);
136
+ throw err;
137
+ }
138
+
139
+ const ACCOUNT_ERROR_CODES = {
140
+ 1357001: "Account blocked - Facebook detected automated behavior",
141
+ 1357004: "Account checkpoint required - Please verify your account on facebook.com",
142
+ 1357031: "Account temporarily locked - Too many login attempts",
143
+ 1357033: "Account suspended - Violation of terms of service",
144
+ 2056003: "Account restricted - Suspicious activity detected"
145
+ };
146
+
147
+ if (res.error && ACCOUNT_ERROR_CODES[res.error]) {
148
+ const err = new Error(ACCOUNT_ERROR_CODES[res.error]);
149
+ err.error = "Account security issue";
150
+ err.errorCode = res.error;
151
+ err.errorType = res.error === 1357004 ? "CHECKPOINT" : res.error === 1357031 ? "LOCKED" : "BLOCKED";
152
+ err.requiresReLogin = res.error === 1357004 || res.error === 1357031;
153
+ warn("Account Status", `${ACCOUNT_ERROR_CODES[res.error]} (Code: ${res.error})`);
154
+ throw err;
155
+ }
156
+
157
+ if (res.error === 1357001 || (res.errorSummary && res.errorSummary.includes("blocked"))) {
158
+ const err = new Error("Facebook blocked the login");
159
+ err.error = "Not logged in.";
160
+ err.errorType = "BLOCKED";
161
+ throw err;
162
+ }
163
+
164
+ const resStr = JSON.stringify(res);
165
+
166
+ if (resStr.includes("XCheckpointFBScrapingWarningController") || resStr.includes("601051028565049")) {
167
+ warn("Bot Detection", "Facebook checkpoint detected - scraping warning (601051028565049)");
168
+ try {
169
+ globalRateLimiter.setEndpointCooldown("__GLOBAL__", 5 * 60 * 1000);
170
+ configureRateLimiter({ maxConcurrentRequests: 2 });
171
+ } catch (_) {}
172
+ const err = new Error("Facebook detected automated behavior - Account may be flagged");
173
+ err.error = "Bot checkpoint detected";
174
+ err.errorCode = "CHECKPOINT_SCRAPING";
175
+ err.errorType = "BOT_DETECTION";
176
+ err.requiresReLogin = true;
177
+ throw err;
178
+ }
179
+
180
+ if (resStr.includes("1501092823525282")) {
181
+ warn("Bot Detection", "Critical bot checkpoint 282 detected! Account requires immediate attention!");
182
+ log("Please check your Facebook account in a browser and complete any security checks.");
183
+ try {
184
+ globalRateLimiter.setEndpointCooldown("__GLOBAL__", 10 * 60 * 1000);
185
+ configureRateLimiter({ maxConcurrentRequests: 1 });
186
+ } catch (_) {}
187
+ const err = new Error("Facebook detected automated behavior - Critical checkpoint required");
188
+ err.error = "Critical bot checkpoint";
189
+ err.errorCode = "CHECKPOINT_282";
190
+ err.errorType = "BOT_DETECTION_CRITICAL";
191
+ err.requiresReLogin = true;
192
+ throw err;
193
+ }
194
+
195
+ if (resStr.includes("828281030927956")) {
196
+ warn("Bot Detection", "Bot checkpoint 956 detected - Account may be restricted");
197
+ log("Please verify your Facebook account status in a browser.");
198
+ }
199
+
200
+ if (resStr.includes("https://www.facebook.com/login.php?") || String(res.redirect || "").includes("login.php?")) {
201
+ warn("Session Status", "Redirected to login page - Session expired");
202
+ const err = new Error("Session expired - Redirected to login page");
203
+ err.error = 401;
204
+ err.errorCode = 401;
205
+ err.errorType = "LOGIN_REDIRECT";
206
+ err.requiresReLogin = true;
207
+ throw err;
208
+ }
209
+
210
+ if (typeof data.body === 'string' && (data.body.includes('<title>Facebook - Log In or Sign Up</title>') || data.body.includes('name="login_form"'))) {
211
+ const err = new Error("Session expired - Redirected to login page");
212
+ err.error = 401;
213
+ err.errorCode = 401;
214
+ err.errorType = "LOGIN_REDIRECT";
215
+ err.requiresReLogin = true;
216
+ warn("Session Status", "Detected login page redirect. Session expired.");
217
+ throw err;
218
+ }
219
+
220
+ return res;
221
+ };
222
+ }
223
+
224
+ /**
225
+ * Saves cookies from a response to the cookie jar.
226
+ * @param {Object} jar - The cookie jar instance.
227
+ * @returns {function(res: Object): Object} A function that processes the response and returns it.
228
+ */
229
+ function saveCookies(jar) {
230
+ return function (res) {
231
+ const cookies = res.headers["set-cookie"] || [];
232
+ cookies.forEach(function (c) {
233
+ if (c.indexOf(".facebook.com") > -1) {
234
+ jar.setCookie(c, "https://www.facebook.com");
235
+ }
236
+ const c2 = c.replace(/domain=\.facebook\.com/, "domain=.messenger.com");
237
+ jar.setCookie(c2, "https://www.messenger.com");
238
+ });
239
+ return res;
240
+ };
241
+ }
242
+
243
+ /**
244
+ * Retrieves an access token from a business account page.
245
+ * @param {Object} jar - The cookie jar instance.
246
+ * @param {Object} Options - Global request options.
247
+ * @returns {function(res: Object): Promise<[string, string|null]>}
248
+ */
249
+ function getAccessFromBusiness(jar, Options) {
250
+ return async function (res) {
251
+ const html = res ? res.body : null;
252
+ const { get } = require("./request");
253
+ try {
254
+ const businessRes = await get("https://business.facebook.com/content_management", jar, null, Options, null, { noRef: true });
255
+ const token = /"accessToken":"([^.]+)","clientID":/g.exec(businessRes.body)[1];
256
+ return [html, token];
257
+ } catch (e) {
258
+ return [html, null];
259
+ }
260
+ };
261
+ }
262
+
263
+ /**
264
+ * Retrieves all cookies from the jar for both Facebook and Messenger domains.
265
+ * @param {Object} jar - The cookie jar instance.
266
+ * @returns {Array<Object>} An array of cookie objects.
267
+ */
268
+ function getAppState(jar) {
269
+ return jar
270
+ .getCookiesSync("https://www.facebook.com")
271
+ .concat(jar.getCookiesSync("https://www.messenger.com"));
272
+ }
273
+
274
+ module.exports = {
275
+ parseAndCheckLogin,
276
+ saveCookies,
277
+ getAccessFromBusiness,
278
+ getAppState,
279
+ };