fca-neokex-fix 1.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.
- package/CHANGELOG.md +220 -0
- package/LICENSE +26 -0
- package/README.md +346 -0
- package/THEME_FEATURES.md +137 -0
- package/examples/README.md +131 -0
- package/examples/apply-ai-theme.js +127 -0
- package/examples/check-current-theme.js +74 -0
- package/examples/simple-bot.js +114 -0
- package/examples/test-bot.js +752 -0
- package/examples/test-logging.js +85 -0
- package/examples/theme-usage-example.js +53 -0
- package/index.js +2 -0
- package/package.json +105 -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/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/fetchThemeData.js +65 -0
- package/src/apis/follow.js +81 -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/getFriendsList.js +79 -0
- package/src/apis/getMessage.js +423 -0
- package/src/apis/getTheme.js +104 -0
- package/src/apis/getThemeInfo.js +96 -0
- package/src/apis/getThreadHistory.js +239 -0
- package/src/apis/getThreadInfo.js +257 -0
- package/src/apis/getThreadList.js +222 -0
- package/src/apis/getThreadPictures.js +58 -0
- package/src/apis/getUserID.js +83 -0
- package/src/apis/getUserInfo.js +495 -0
- package/src/apis/getUserInfoV2.js +146 -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 +796 -0
- package/src/apis/listenSpeed.js +170 -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 +41 -0
- package/src/apis/markAsSeen.js +70 -0
- package/src/apis/mqttDeltaValue.js +330 -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 +141 -0
- package/src/apis/produceMetaTheme.js +180 -0
- package/src/apis/realtime.js +161 -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/sendMessage.js +281 -0
- package/src/apis/sendMessageMqtt.js +188 -0
- package/src/apis/sendTypingIndicator.js +41 -0
- package/src/apis/setMessageReaction.js +27 -0
- package/src/apis/setMessageReactionMqtt.js +61 -0
- package/src/apis/setThreadTheme.js +260 -0
- package/src/apis/setThreadThemeMqtt.js +94 -0
- package/src/apis/share.js +107 -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/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 +91 -0
- package/src/engine/models/buildAPI.js +109 -0
- package/src/engine/models/loginHelper.js +326 -0
- package/src/engine/models/setOptions.js +53 -0
- package/src/utils/auth-helpers.js +149 -0
- package/src/utils/autoReLogin.js +169 -0
- package/src/utils/axios.js +290 -0
- package/src/utils/clients.js +270 -0
- package/src/utils/constants.js +396 -0
- package/src/utils/formatters/data/formatAttachment.js +370 -0
- package/src/utils/formatters/data/formatDelta.js +153 -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 +1067 -0
- package/src/utils/headers.js +199 -0
- package/src/utils/index.js +151 -0
- package/src/utils/monitoring.js +358 -0
- package/src/utils/rateLimiter.js +380 -0
- package/src/utils/tokenRefresh.js +311 -0
- package/src/utils/user-agents.js +238 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { makeParsable, log, warn } = require("./constants");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Formats a cookie array into a string for use in a cookie jar.
|
|
7
|
+
* @param {Array<string>} arr - An array containing cookie parts.
|
|
8
|
+
* @param {string} url - The base URL for the cookie domain.
|
|
9
|
+
* @returns {string} The formatted cookie string.
|
|
10
|
+
*/
|
|
11
|
+
function formatCookie(arr, url) {
|
|
12
|
+
return arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + url + ".com";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Parses a response from Facebook, checks for login status, and handles retries.
|
|
17
|
+
* @param {Object} ctx - The application context.
|
|
18
|
+
* @param {Object} http - The HTTP request functions.
|
|
19
|
+
* @param {number} [retryCount=0] - The current retry count for the request.
|
|
20
|
+
* @returns {function(data: Object): Promise<Object>} A function that processes the response data.
|
|
21
|
+
*/
|
|
22
|
+
function parseAndCheckLogin(ctx, http, retryCount = 0) {
|
|
23
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
24
|
+
|
|
25
|
+
return async (data) => {
|
|
26
|
+
if (data.statusCode === 401) {
|
|
27
|
+
const err = new Error("Session expired - Authentication required");
|
|
28
|
+
err.error = 401;
|
|
29
|
+
err.errorCode = 401;
|
|
30
|
+
err.errorType = "AUTHENTICATION_REQUIRED";
|
|
31
|
+
err.requiresReLogin = true;
|
|
32
|
+
warn("Session Status", "Session expired. Re-login required.");
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (data.statusCode >= 500 && data.statusCode < 600) {
|
|
37
|
+
if (retryCount >= 5) {
|
|
38
|
+
const err = new Error("Request retry failed. Check the `res` and `statusCode` property on this error.");
|
|
39
|
+
err.statusCode = data.statusCode;
|
|
40
|
+
err.res = data.body;
|
|
41
|
+
err.error = "Request retry failed. Check the `res` and `statusCode` property on this error.";
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
retryCount++;
|
|
46
|
+
const retryTime = Math.floor(Math.random() * 5000);
|
|
47
|
+
const url = data.request.uri.protocol + "//" + data.request.uri.hostname + data.request.uri.pathname;
|
|
48
|
+
|
|
49
|
+
await delay(retryTime);
|
|
50
|
+
|
|
51
|
+
if (data.request.headers["content-type"].split(";")[0] === "multipart/form-data") {
|
|
52
|
+
const newData = await http.postFormData(
|
|
53
|
+
url,
|
|
54
|
+
ctx.jar,
|
|
55
|
+
data.request.formData,
|
|
56
|
+
data.request.qs,
|
|
57
|
+
ctx.globalOptions,
|
|
58
|
+
ctx
|
|
59
|
+
);
|
|
60
|
+
return await parseAndCheckLogin(ctx, http, retryCount)(newData);
|
|
61
|
+
} else {
|
|
62
|
+
const newData = await http.post(
|
|
63
|
+
url,
|
|
64
|
+
ctx.jar,
|
|
65
|
+
data.request.form,
|
|
66
|
+
ctx.globalOptions,
|
|
67
|
+
ctx
|
|
68
|
+
);
|
|
69
|
+
return await parseAndCheckLogin(ctx, http, retryCount)(newData);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (data.statusCode === 404) return;
|
|
74
|
+
|
|
75
|
+
if (data.statusCode !== 200) {
|
|
76
|
+
throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let res = null;
|
|
80
|
+
|
|
81
|
+
if (typeof data.body === 'object' && data.body !== null) {
|
|
82
|
+
res = data.body;
|
|
83
|
+
} else if (typeof data.body === 'string') {
|
|
84
|
+
try {
|
|
85
|
+
res = JSON.parse(makeParsable(data.body));
|
|
86
|
+
} catch (e) {
|
|
87
|
+
const err = new Error("JSON.parse error. Check the `detail` property on this error.");
|
|
88
|
+
err.error = "JSON.parse error. Check the `detail` property on this error.";
|
|
89
|
+
err.detail = e;
|
|
90
|
+
err.res = data.body;
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
throw new Error("Unknown response body type: " + typeof data.body);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (res.redirect && data.request.method === "GET") {
|
|
98
|
+
const redirectRes = await http.get(res.redirect, ctx.jar);
|
|
99
|
+
return await parseAndCheckLogin(ctx, http)(redirectRes);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (res.jsmods && res.jsmods.require && Array.isArray(res.jsmods.require[0]) && res.jsmods.require[0][0] === "Cookie") {
|
|
103
|
+
res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
|
|
104
|
+
const requireCookie = res.jsmods.require[0][3];
|
|
105
|
+
ctx.jar.setCookie(formatCookie(requireCookie, "facebook"), "https://www.facebook.com");
|
|
106
|
+
ctx.jar.setCookie(formatCookie(requireCookie, "messenger"), "https://www.messenger.com");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (res.jsmods && Array.isArray(res.jsmods.require)) {
|
|
110
|
+
const arr = res.jsmods.require;
|
|
111
|
+
for (const i in arr) {
|
|
112
|
+
if (arr[i][0] === "DTSG" && arr[i][1] === "setToken") {
|
|
113
|
+
ctx.fb_dtsg = arr[i][3][0];
|
|
114
|
+
ctx.ttstamp = "2";
|
|
115
|
+
for (let j = 0; j < ctx.fb_dtsg.length; j++) {
|
|
116
|
+
ctx.ttstamp += ctx.fb_dtsg.charCodeAt(j);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const SESSION_EXPIRY_CODES = {
|
|
123
|
+
1357046: "Session token expired - Re-authentication required",
|
|
124
|
+
1357045: "Invalid session token - Re-login needed",
|
|
125
|
+
458: "Session expired - User not logged in"
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
if (res.error && SESSION_EXPIRY_CODES[res.error]) {
|
|
129
|
+
const err = new Error(SESSION_EXPIRY_CODES[res.error]);
|
|
130
|
+
err.error = res.error;
|
|
131
|
+
err.errorCode = res.error;
|
|
132
|
+
err.errorType = "SESSION_EXPIRED";
|
|
133
|
+
err.requiresReLogin = true;
|
|
134
|
+
warn("Session Status", `${SESSION_EXPIRY_CODES[res.error]} (Code: ${res.error})`);
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const ACCOUNT_ERROR_CODES = {
|
|
139
|
+
1357001: "Account blocked - Facebook detected automated behavior",
|
|
140
|
+
1357004: "Account checkpoint required - Please verify your account on facebook.com",
|
|
141
|
+
1357031: "Account temporarily locked - Too many login attempts",
|
|
142
|
+
1357033: "Account suspended - Violation of terms of service",
|
|
143
|
+
2056003: "Account restricted - Suspicious activity detected"
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
if (res.error && ACCOUNT_ERROR_CODES[res.error]) {
|
|
147
|
+
const err = new Error(ACCOUNT_ERROR_CODES[res.error]);
|
|
148
|
+
err.error = "Account security issue";
|
|
149
|
+
err.errorCode = res.error;
|
|
150
|
+
err.errorType = res.error === 1357004 ? "CHECKPOINT" : res.error === 1357031 ? "LOCKED" : "BLOCKED";
|
|
151
|
+
err.requiresReLogin = res.error === 1357004 || res.error === 1357031;
|
|
152
|
+
warn("Account Status", `${ACCOUNT_ERROR_CODES[res.error]} (Code: ${res.error})`);
|
|
153
|
+
throw err;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (res.error === 1357001 || (res.errorSummary && res.errorSummary.includes("blocked"))) {
|
|
157
|
+
const err = new Error("Facebook blocked the login");
|
|
158
|
+
err.error = "Not logged in.";
|
|
159
|
+
err.errorType = "BLOCKED";
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const resStr = JSON.stringify(res);
|
|
164
|
+
|
|
165
|
+
if (resStr.includes("XCheckpointFBScrapingWarningController") || resStr.includes("601051028565049")) {
|
|
166
|
+
warn("Bot Detection", "Facebook checkpoint detected - scraping warning (601051028565049)");
|
|
167
|
+
const err = new Error("Facebook detected automated behavior - Account may be flagged");
|
|
168
|
+
err.error = "Bot checkpoint detected";
|
|
169
|
+
err.errorCode = "CHECKPOINT_SCRAPING";
|
|
170
|
+
err.errorType = "BOT_DETECTION";
|
|
171
|
+
err.requiresReLogin = true;
|
|
172
|
+
throw err;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (resStr.includes("1501092823525282")) {
|
|
176
|
+
warn("Bot Detection", "Critical bot checkpoint 282 detected! Account requires immediate attention!");
|
|
177
|
+
log("Please check your Facebook account in a browser and complete any security checks.");
|
|
178
|
+
const err = new Error("Facebook detected automated behavior - Critical checkpoint required");
|
|
179
|
+
err.error = "Critical bot checkpoint";
|
|
180
|
+
err.errorCode = "CHECKPOINT_282";
|
|
181
|
+
err.errorType = "BOT_DETECTION_CRITICAL";
|
|
182
|
+
err.requiresReLogin = true;
|
|
183
|
+
throw err;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (resStr.includes("828281030927956")) {
|
|
187
|
+
warn("Bot Detection", "Bot checkpoint 956 detected - Account may be restricted");
|
|
188
|
+
log("Please verify your Facebook account status in a browser.");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (resStr.includes("https://www.facebook.com/login.php?") || String(res.redirect || "").includes("login.php?")) {
|
|
192
|
+
warn("Session Status", "Redirected to login page - Session expired");
|
|
193
|
+
const err = new Error("Session expired - Redirected to login page");
|
|
194
|
+
err.error = 401;
|
|
195
|
+
err.errorCode = 401;
|
|
196
|
+
err.errorType = "LOGIN_REDIRECT";
|
|
197
|
+
err.requiresReLogin = true;
|
|
198
|
+
throw err;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (typeof data.body === 'string' && (data.body.includes('<title>Facebook - Log In or Sign Up</title>') || data.body.includes('name="login_form"'))) {
|
|
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
|
+
warn("Session Status", "Detected login page redirect. Session expired.");
|
|
208
|
+
throw err;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return res;
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Saves cookies from a response to the cookie jar.
|
|
217
|
+
* @param {Object} jar - The cookie jar instance.
|
|
218
|
+
* @returns {function(res: Object): Object} A function that processes the response and returns it.
|
|
219
|
+
*/
|
|
220
|
+
function saveCookies(jar) {
|
|
221
|
+
return function (res) {
|
|
222
|
+
const cookies = res.headers["set-cookie"] || [];
|
|
223
|
+
cookies.forEach(function (c) {
|
|
224
|
+
if (c.indexOf(".facebook.com") > -1) {
|
|
225
|
+
jar.setCookie(c, "https://www.facebook.com");
|
|
226
|
+
}
|
|
227
|
+
const c2 = c.replace(/domain=\.facebook\.com/, "domain=.messenger.com");
|
|
228
|
+
jar.setCookie(c2, "https://www.messenger.com");
|
|
229
|
+
});
|
|
230
|
+
return res;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Retrieves an access token from a business account page.
|
|
236
|
+
* @param {Object} jar - The cookie jar instance.
|
|
237
|
+
* @param {Object} Options - Global request options.
|
|
238
|
+
* @returns {function(res: Object): Promise<[string, string|null]>}
|
|
239
|
+
*/
|
|
240
|
+
function getAccessFromBusiness(jar, Options) {
|
|
241
|
+
return async function (res) {
|
|
242
|
+
const html = res ? res.body : null;
|
|
243
|
+
const { get } = require("./request");
|
|
244
|
+
try {
|
|
245
|
+
const businessRes = await get("https://business.facebook.com/content_management", jar, null, Options, null, { noRef: true });
|
|
246
|
+
const token = /"accessToken":"([^.]+)","clientID":/g.exec(businessRes.body)[1];
|
|
247
|
+
return [html, token];
|
|
248
|
+
} catch (e) {
|
|
249
|
+
return [html, null];
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Retrieves all cookies from the jar for both Facebook and Messenger domains.
|
|
256
|
+
* @param {Object} jar - The cookie jar instance.
|
|
257
|
+
* @returns {Array<Object>} An array of cookie objects.
|
|
258
|
+
*/
|
|
259
|
+
function getAppState(jar) {
|
|
260
|
+
return jar
|
|
261
|
+
.getCookiesSync("https://www.facebook.com")
|
|
262
|
+
.concat(jar.getCookiesSync("https://www.messenger.com"));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
module.exports = {
|
|
266
|
+
parseAndCheckLogin,
|
|
267
|
+
saveCookies,
|
|
268
|
+
getAccessFromBusiness,
|
|
269
|
+
getAppState,
|
|
270
|
+
};
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
/* eslint-disable no-prototype-builtins */
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const chalk = require("chalk");
|
|
5
|
+
const gradient = require("gradient-string");
|
|
6
|
+
|
|
7
|
+
const brandGradient = gradient(["#0061ff", "#681297"]);
|
|
8
|
+
const successGradient = gradient(["#00ff87", "#60efff"]);
|
|
9
|
+
const errorGradient = gradient(["#ff0000", "#ff006e"]);
|
|
10
|
+
const warnGradient = gradient(["#ffbe0b", "#fb5607"]);
|
|
11
|
+
const infoGradient = gradient(["#3a86ff", "#8338ec"]);
|
|
12
|
+
const debugGradient = gradient(["#06ffa5", "#00d9ff"]);
|
|
13
|
+
|
|
14
|
+
const ws = brandGradient("NeoKEX - FCA");
|
|
15
|
+
|
|
16
|
+
let h;
|
|
17
|
+
const i = {};
|
|
18
|
+
const j = {
|
|
19
|
+
_: "%",
|
|
20
|
+
A: "%2",
|
|
21
|
+
B: "000",
|
|
22
|
+
C: "%7d",
|
|
23
|
+
D: "%7b%22",
|
|
24
|
+
E: "%2c%22",
|
|
25
|
+
F: "%22%3a",
|
|
26
|
+
G: "%2c%22ut%22%3a1",
|
|
27
|
+
H: "%2c%22bls%22%3a",
|
|
28
|
+
I: "%2c%22n%22%3a%22%",
|
|
29
|
+
J: "%22%3a%7b%22i%22%3a0%7d",
|
|
30
|
+
K: "%2c%22pt%22%3a0%2c%22vis%22%3a",
|
|
31
|
+
L: "%2c%22ch%22%3a%7b%22h%22%3a%22",
|
|
32
|
+
M: "%7b%22v%22%3a2%2c%22time%22%3a1",
|
|
33
|
+
N: ".channel%22%2c%22sub%22%3a%5b",
|
|
34
|
+
O: "%2c%22sb%22%3a1%2c%22t%22%3a%5b",
|
|
35
|
+
P: "%2c%22ud%22%3a100%2c%22lc%22%3a0",
|
|
36
|
+
Q: "%5d%2c%22f%22%3anull%2c%22uct%22%3a",
|
|
37
|
+
R: ".channel%22%2c%22sub%22%3a%5b1%5d",
|
|
38
|
+
S: "%22%2c%22m%22%3a0%7d%2c%7b%22i%22%3a",
|
|
39
|
+
T: "%2c%22blc%22%3a1%2c%22snd%22%3a1%2c%22ct%22%3a",
|
|
40
|
+
U: "%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a",
|
|
41
|
+
V: "%2c%22blc%22%3a0%2c%22snd%22%3a0%2c%22ct%22%3a",
|
|
42
|
+
W: "%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a",
|
|
43
|
+
X: "%2c%22ri%22%3a0%7d%2c%22state%22%3a%7b%22p%22%3a0%2c%22ut%22%3a1",
|
|
44
|
+
Y: "%2c%22pt%22%3a0%2c%22vis%22%3a1%2c%22bls%22%3a0%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a",
|
|
45
|
+
Z: "%2c%22sb%22%3a1%2c%22t%22%3a%5b%5d%2c%22f%22%3anull%2c%22uct%22%3a0%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a",
|
|
46
|
+
};
|
|
47
|
+
(function () {
|
|
48
|
+
const l = [];
|
|
49
|
+
for (const m in j) {
|
|
50
|
+
i[j[m]] = m;
|
|
51
|
+
l.push(j[m]);
|
|
52
|
+
}
|
|
53
|
+
l.reverse();
|
|
54
|
+
h = new RegExp(l.join("|"), "g");
|
|
55
|
+
})();
|
|
56
|
+
|
|
57
|
+
const NUM_TO_MONTH = [
|
|
58
|
+
"Jan",
|
|
59
|
+
"Feb",
|
|
60
|
+
"Mar",
|
|
61
|
+
"Apr",
|
|
62
|
+
"May",
|
|
63
|
+
"Jun",
|
|
64
|
+
"Jul",
|
|
65
|
+
"Aug",
|
|
66
|
+
"Sep",
|
|
67
|
+
"Oct",
|
|
68
|
+
"Nov",
|
|
69
|
+
"Dec",
|
|
70
|
+
];
|
|
71
|
+
const NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
72
|
+
|
|
73
|
+
function getRandom(arr) {
|
|
74
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function padZeros(val, len) {
|
|
78
|
+
val = String(val);
|
|
79
|
+
len = len || 2;
|
|
80
|
+
while (val.length < len) val = "0" + val;
|
|
81
|
+
return val;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function generateThreadingID(clientID) {
|
|
85
|
+
const k = Date.now();
|
|
86
|
+
const l = Math.floor(Math.random() * 4294967295);
|
|
87
|
+
const m = clientID;
|
|
88
|
+
return "<" + k + ":" + l + "-" + m + "@mail.projektitan.com>";
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function binaryToDecimal(data) {
|
|
92
|
+
let ret = "";
|
|
93
|
+
while (data !== "0") {
|
|
94
|
+
let end = 0;
|
|
95
|
+
let fullName = "";
|
|
96
|
+
let i = 0;
|
|
97
|
+
for (; i < data.length; i++) {
|
|
98
|
+
end = 2 * end + parseInt(data[i], 10);
|
|
99
|
+
if (end >= 10) {
|
|
100
|
+
fullName += "1";
|
|
101
|
+
end -= 10;
|
|
102
|
+
} else {
|
|
103
|
+
fullName += "0";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
ret = end.toString() + ret;
|
|
107
|
+
data = fullName.slice(fullName.indexOf("1"));
|
|
108
|
+
}
|
|
109
|
+
return ret;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function generateOfflineThreadingID() {
|
|
113
|
+
const ret = Date.now();
|
|
114
|
+
const value = Math.floor(Math.random() * 4294967295);
|
|
115
|
+
const str = ("0000000000000000000000" + value.toString(2)).slice(-22);
|
|
116
|
+
const msgs = ret.toString(2) + str;
|
|
117
|
+
return binaryToDecimal(msgs);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function presenceEncode(str) {
|
|
121
|
+
return encodeURIComponent(str)
|
|
122
|
+
.replace(/([_A-Z])|%../g, function (m, n) {
|
|
123
|
+
return n ? "%" + n.charCodeAt(0).toString(16) : m;
|
|
124
|
+
})
|
|
125
|
+
.toLowerCase()
|
|
126
|
+
.replace(h, function (m) {
|
|
127
|
+
return i[m];
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function presenceDecode(str) {
|
|
132
|
+
return decodeURIComponent(
|
|
133
|
+
str.replace(/[_A-Z]/g, function (m) {
|
|
134
|
+
return j[m];
|
|
135
|
+
})
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function generatePresence(userID) {
|
|
140
|
+
const time = Date.now();
|
|
141
|
+
return (
|
|
142
|
+
"E" +
|
|
143
|
+
presenceEncode(
|
|
144
|
+
JSON.stringify({
|
|
145
|
+
v: 3,
|
|
146
|
+
time: parseInt(time / 1000, 10),
|
|
147
|
+
user: userID,
|
|
148
|
+
state: {
|
|
149
|
+
ut: 0,
|
|
150
|
+
t2: [],
|
|
151
|
+
lm2: null,
|
|
152
|
+
uct2: time,
|
|
153
|
+
tr: null,
|
|
154
|
+
tw: Math.floor(Math.random() * 4294967295) + 1,
|
|
155
|
+
at: time,
|
|
156
|
+
},
|
|
157
|
+
ch: {
|
|
158
|
+
["p_" + userID]: 0,
|
|
159
|
+
},
|
|
160
|
+
})
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function generateAccessiblityCookie() {
|
|
166
|
+
const time = Date.now();
|
|
167
|
+
return encodeURIComponent(
|
|
168
|
+
JSON.stringify({
|
|
169
|
+
sr: 0,
|
|
170
|
+
"sr-ts": time,
|
|
171
|
+
jk: 0,
|
|
172
|
+
"jk-ts": time,
|
|
173
|
+
kb: 0,
|
|
174
|
+
"kb-ts": time,
|
|
175
|
+
hcm: 0,
|
|
176
|
+
"hcm-ts": time,
|
|
177
|
+
})
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function getGUID() {
|
|
182
|
+
let sectionLength = Date.now();
|
|
183
|
+
const id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
184
|
+
const r = Math.floor((sectionLength + Math.random() * 16) % 16);
|
|
185
|
+
sectionLength = Math.floor(sectionLength / 16);
|
|
186
|
+
const _guid = (c == "x" ? r : (r & 7) | 8).toString(16);
|
|
187
|
+
return _guid;
|
|
188
|
+
});
|
|
189
|
+
return id;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function getFrom(str, startToken, endToken) {
|
|
193
|
+
const start = str.indexOf(startToken) + startToken.length;
|
|
194
|
+
if (start < startToken.length) return "";
|
|
195
|
+
|
|
196
|
+
const lastHalf = str.substring(start);
|
|
197
|
+
const end = lastHalf.indexOf(endToken);
|
|
198
|
+
if (end === -1) {
|
|
199
|
+
throw Error(
|
|
200
|
+
"Could not find endTime `" + endToken + "` in the given string."
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return lastHalf.substring(0, end);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function makeParsable(html) {
|
|
207
|
+
const withoutForLoop = html.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, "");
|
|
208
|
+
const maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
|
|
209
|
+
if (maybeMultipleObjects.length === 1) return maybeMultipleObjects;
|
|
210
|
+
|
|
211
|
+
return "[" + maybeMultipleObjects.join("},{") + "]";
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function arrToForm(form) {
|
|
215
|
+
return arrayToObject(
|
|
216
|
+
form,
|
|
217
|
+
function (v) {
|
|
218
|
+
return v.name;
|
|
219
|
+
},
|
|
220
|
+
function (v) {
|
|
221
|
+
return v.val;
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function arrayToObject(arr, getKey, getValue) {
|
|
227
|
+
return arr.reduce(function (acc, val) {
|
|
228
|
+
acc[getKey(val)] = getValue(val);
|
|
229
|
+
return acc;
|
|
230
|
+
}, {});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function getSignatureID() {
|
|
234
|
+
return Math.floor(Math.random() * 2147483648).toString(16);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function generateTimestampRelative() {
|
|
238
|
+
const d = new Date();
|
|
239
|
+
return d.getHours() + ":" + padZeros(d.getMinutes());
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function getType(obj) {
|
|
243
|
+
return Object.prototype.toString.call(obj).slice(8, -1);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
let logging = true;
|
|
248
|
+
let logLevel = 'info';
|
|
249
|
+
|
|
250
|
+
const logLevels = {
|
|
251
|
+
trace: 0,
|
|
252
|
+
debug: 1,
|
|
253
|
+
info: 2,
|
|
254
|
+
warn: 3,
|
|
255
|
+
error: 4,
|
|
256
|
+
silent: 5
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
function logOptions(bool) {
|
|
260
|
+
logging = bool;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function setLogLevel(level) {
|
|
264
|
+
if (logLevels.hasOwnProperty(level)) {
|
|
265
|
+
logLevel = level;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function getTimestamp() {
|
|
270
|
+
const now = new Date();
|
|
271
|
+
return chalk.gray.dim(`[${padZeros(now.getHours())}:${padZeros(now.getMinutes())}:${padZeros(now.getSeconds())}]`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function shouldLog(level) {
|
|
275
|
+
return logging && logLevels[level] >= logLevels[logLevel];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function trace(...args) {
|
|
279
|
+
if (!shouldLog('trace')) return;
|
|
280
|
+
console.log(getTimestamp(), ws, debugGradient("◆ TRACE"), chalk.cyan(...args));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function debug(...args) {
|
|
284
|
+
if (!shouldLog('debug')) return;
|
|
285
|
+
console.log(getTimestamp(), ws, debugGradient("◆ DEBUG"), chalk.blue(...args));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function info(...args) {
|
|
289
|
+
if (!shouldLog('info')) return;
|
|
290
|
+
console.log(getTimestamp(), ws, infoGradient("◆ INFO"), chalk.white(...args));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function log(...args) {
|
|
294
|
+
if (!shouldLog('info')) return;
|
|
295
|
+
console.log(getTimestamp(), ws, successGradient("◆ LOG"), chalk.green(...args));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function success(...args) {
|
|
299
|
+
if (logging === false) return;
|
|
300
|
+
console.log(getTimestamp(), ws, successGradient("✓ SUCCESS"), chalk.greenBright.bold(...args));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function warn(...args) {
|
|
304
|
+
if (!shouldLog('warn')) return;
|
|
305
|
+
console.warn(getTimestamp(), ws, warnGradient("⚠ WARNING"), chalk.yellow(...args));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function error(...args) {
|
|
309
|
+
if (!shouldLog('error')) return;
|
|
310
|
+
console.error(getTimestamp(), ws, errorGradient("✖ ERROR"), chalk.red.bold(...args));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function critical(...args) {
|
|
314
|
+
if (!shouldLog('error')) return;
|
|
315
|
+
console.error(getTimestamp(), ws, errorGradient("☠ CRITICAL"), chalk.bgRed.white.bold(...args));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function banner(message, color = 'cyan') {
|
|
319
|
+
if (!shouldLog('info')) return;
|
|
320
|
+
const line = '═'.repeat(message.length + 4);
|
|
321
|
+
const colorFunc = chalk[color] || chalk.cyan;
|
|
322
|
+
console.log(colorFunc(`╔${line}╗`));
|
|
323
|
+
console.log(colorFunc(`║ ${message} ║`));
|
|
324
|
+
console.log(colorFunc(`╚${line}╝`));
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function box(title, content, style = 'info') {
|
|
328
|
+
if (!shouldLog('info')) return;
|
|
329
|
+
const contentLines = Array.isArray(content) ? content : [content];
|
|
330
|
+
const maxLength = Math.max(title.length, ...contentLines.map(l => String(l).length));
|
|
331
|
+
const topLine = '┌─' + '─'.repeat(maxLength + 2) + '─┐';
|
|
332
|
+
const bottomLine = '└─' + '─'.repeat(maxLength + 2) + '─┘';
|
|
333
|
+
const titleLine = `│ ${chalk.bold(title)}${' '.repeat(maxLength - title.length + 1)} │`;
|
|
334
|
+
|
|
335
|
+
const colorMap = {
|
|
336
|
+
info: chalk.cyan,
|
|
337
|
+
success: chalk.green,
|
|
338
|
+
warn: chalk.yellow,
|
|
339
|
+
error: chalk.red,
|
|
340
|
+
debug: chalk.blue
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const colorFunc = colorMap[style] || chalk.cyan;
|
|
344
|
+
|
|
345
|
+
console.log(colorFunc(topLine));
|
|
346
|
+
console.log(colorFunc(titleLine));
|
|
347
|
+
console.log(colorFunc('├─' + '─'.repeat(maxLength + 2) + '─┤'));
|
|
348
|
+
contentLines.forEach(line => {
|
|
349
|
+
const paddedLine = String(line) + ' '.repeat(maxLength - String(line).length);
|
|
350
|
+
console.log(colorFunc(`│ ${paddedLine} │`));
|
|
351
|
+
});
|
|
352
|
+
console.log(colorFunc(bottomLine));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
module.exports = {
|
|
356
|
+
ws,
|
|
357
|
+
chalk,
|
|
358
|
+
gradient,
|
|
359
|
+
brandGradient,
|
|
360
|
+
successGradient,
|
|
361
|
+
errorGradient,
|
|
362
|
+
warnGradient,
|
|
363
|
+
infoGradient,
|
|
364
|
+
debugGradient,
|
|
365
|
+
logOptions,
|
|
366
|
+
setLogLevel,
|
|
367
|
+
trace,
|
|
368
|
+
debug,
|
|
369
|
+
info,
|
|
370
|
+
log,
|
|
371
|
+
success,
|
|
372
|
+
warn,
|
|
373
|
+
error,
|
|
374
|
+
critical,
|
|
375
|
+
banner,
|
|
376
|
+
box,
|
|
377
|
+
getRandom,
|
|
378
|
+
padZeros,
|
|
379
|
+
generateThreadingID,
|
|
380
|
+
binaryToDecimal,
|
|
381
|
+
generateOfflineThreadingID,
|
|
382
|
+
presenceEncode,
|
|
383
|
+
presenceDecode,
|
|
384
|
+
generatePresence,
|
|
385
|
+
generateAccessiblityCookie,
|
|
386
|
+
getGUID,
|
|
387
|
+
getFrom,
|
|
388
|
+
makeParsable,
|
|
389
|
+
arrToForm,
|
|
390
|
+
arrayToObject,
|
|
391
|
+
getSignatureID,
|
|
392
|
+
generateTimestampRelative,
|
|
393
|
+
getType,
|
|
394
|
+
NUM_TO_MONTH,
|
|
395
|
+
NUM_TO_DAY,
|
|
396
|
+
};
|