@cexy/hoonfca 1.0.7 → 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.
- package/LICENSE +3 -0
- package/examples/login-with-cookies.js +102 -0
- package/examples/verify.js +70 -0
- package/index.js +2 -8
- package/package.json +82 -61
- package/src/{api/action → apis}/addExternalModule.js +24 -25
- package/src/apis/addUserToGroup.js +108 -0
- package/src/apis/changeAdminStatus.js +148 -0
- package/src/apis/changeArchivedStatus.js +61 -0
- package/src/apis/changeAvatar.js +103 -0
- package/src/apis/changeBio.js +69 -0
- package/src/apis/changeBlockedStatus.js +54 -0
- package/src/apis/changeGroupImage.js +136 -0
- package/src/apis/changeThreadColor.js +116 -0
- package/src/apis/changeThreadEmoji.js +53 -0
- package/src/apis/comment.js +207 -0
- package/src/apis/createAITheme.js +129 -0
- package/src/apis/createNewGroup.js +79 -0
- package/src/apis/createPoll.js +73 -0
- package/src/apis/deleteMessage.js +44 -0
- package/src/apis/deleteThread.js +52 -0
- package/src/apis/e2ee.js +17 -0
- package/src/apis/editMessage.js +70 -0
- package/src/apis/emoji.js +124 -0
- package/src/apis/fetchThemeData.js +82 -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 +95 -0
- package/src/apis/getThemeInfo.js +116 -0
- package/src/apis/getThreadHistory.js +239 -0
- package/src/apis/getThreadInfo.js +267 -0
- package/src/apis/getThreadList.js +232 -0
- package/src/apis/getThreadPictures.js +58 -0
- package/src/apis/getUserID.js +117 -0
- package/src/apis/getUserInfo.js +513 -0
- package/src/{api/users → apis}/getUserInfoV2.js +146 -134
- 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 +1236 -0
- package/src/apis/listenSpeed.js +179 -0
- package/src/apis/logout.js +87 -0
- package/src/apis/markAsDelivered.js +47 -0
- package/src/{api/messaging → apis}/markAsRead.js +99 -88
- package/src/apis/markAsReadAll.js +40 -0
- package/src/apis/markAsSeen.js +70 -0
- package/src/apis/mqttDeltaValue.js +278 -0
- package/src/apis/muteThread.js +45 -0
- package/src/apis/nickname.js +132 -0
- package/src/apis/notes.js +163 -0
- package/src/apis/pinMessage.js +150 -0
- package/src/apis/produceMetaTheme.js +180 -0
- package/src/apis/realtime.js +182 -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 +354 -0
- package/src/apis/sendMessageMqtt.js +249 -0
- package/src/apis/sendTypingIndicator.js +91 -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/engine/client.js +92 -0
- package/src/engine/models/buildAPI.js +152 -0
- package/src/engine/models/loginHelper.js +519 -0
- package/src/engine/models/setOptions.js +88 -0
- package/src/security/e2ee.js +109 -0
- package/src/types/index.d.ts +498 -0
- package/src/utils/antiSuspension.js +506 -0
- package/src/utils/auth-helpers.js +149 -0
- package/src/utils/autoReLogin.js +336 -0
- package/src/utils/axios.js +436 -0
- package/src/utils/cache.js +54 -0
- package/src/utils/clients.js +282 -0
- package/src/utils/constants.js +410 -23
- package/src/utils/formatters/data/formatAttachment.js +370 -0
- package/src/utils/formatters/data/formatDelta.js +109 -0
- package/src/utils/formatters/index.js +159 -0
- package/src/utils/formatters/value/formatCookie.js +91 -0
- package/src/utils/formatters/value/formatDate.js +36 -0
- package/src/utils/formatters/value/formatID.js +16 -0
- package/src/utils/formatters.js +1373 -0
- package/src/utils/headers.js +214 -99
- package/src/utils/index.js +153 -0
- package/src/utils/monitoring.js +333 -0
- package/src/utils/rateLimiter.js +319 -0
- package/src/utils/tokenRefresh.js +657 -0
- package/src/utils/user-agents.js +238 -0
- package/src/utils/validation.js +157 -0
- package/CHANGELOG.md +0 -181
- package/DOCS.md +0 -2636
- package/LICENSE-MIT +0 -21
- package/README.md +0 -632
- package/func/checkUpdate.js +0 -233
- package/func/logger.js +0 -48
- package/index.d.ts +0 -746
- package/module/config.js +0 -67
- package/module/login.js +0 -154
- package/module/loginHelper.js +0 -1034
- package/module/options.js +0 -54
- package/src/api/action/changeAvatar.js +0 -137
- package/src/api/action/changeBio.js +0 -75
- package/src/api/action/enableAutoSaveAppState.js +0 -73
- package/src/api/action/getCurrentUserID.js +0 -7
- package/src/api/action/handleFriendRequest.js +0 -57
- package/src/api/action/logout.js +0 -76
- package/src/api/action/refreshFb_dtsg.js +0 -48
- package/src/api/action/setPostReaction.js +0 -106
- package/src/api/action/unfriend.js +0 -54
- package/src/api/http/httpGet.js +0 -46
- package/src/api/http/httpPost.js +0 -52
- package/src/api/http/postFormData.js +0 -47
- package/src/api/messaging/addUserToGroup.js +0 -68
- package/src/api/messaging/changeAdminStatus.js +0 -122
- package/src/api/messaging/changeArchivedStatus.js +0 -55
- package/src/api/messaging/changeBlockedStatus.js +0 -48
- package/src/api/messaging/changeGroupImage.js +0 -90
- package/src/api/messaging/changeNickname.js +0 -70
- package/src/api/messaging/changeThreadColor.js +0 -79
- package/src/api/messaging/changeThreadEmoji.js +0 -106
- package/src/api/messaging/createNewGroup.js +0 -88
- package/src/api/messaging/createPoll.js +0 -43
- package/src/api/messaging/createThemeAI.js +0 -98
- package/src/api/messaging/deleteMessage.js +0 -56
- package/src/api/messaging/deleteThread.js +0 -56
- package/src/api/messaging/editMessage.js +0 -68
- package/src/api/messaging/forwardAttachment.js +0 -51
- package/src/api/messaging/getEmojiUrl.js +0 -29
- package/src/api/messaging/getFriendsList.js +0 -82
- package/src/api/messaging/getMessage.js +0 -829
- package/src/api/messaging/getThemePictures.js +0 -62
- package/src/api/messaging/handleMessageRequest.js +0 -65
- package/src/api/messaging/markAsDelivered.js +0 -57
- package/src/api/messaging/markAsReadAll.js +0 -49
- package/src/api/messaging/markAsSeen.js +0 -61
- package/src/api/messaging/muteThread.js +0 -50
- package/src/api/messaging/removeUserFromGroup.js +0 -106
- package/src/api/messaging/resolvePhotoUrl.js +0 -43
- package/src/api/messaging/scheduler.js +0 -264
- package/src/api/messaging/searchForThread.js +0 -52
- package/src/api/messaging/sendMessage.js +0 -272
- package/src/api/messaging/sendTypingIndicator.js +0 -67
- package/src/api/messaging/setMessageReaction.js +0 -76
- package/src/api/messaging/setTitle.js +0 -119
- package/src/api/messaging/shareContact.js +0 -49
- package/src/api/messaging/threadColors.js +0 -128
- package/src/api/messaging/unsendMessage.js +0 -81
- package/src/api/messaging/uploadAttachment.js +0 -94
- package/src/api/socket/core/connectMqtt.js +0 -255
- package/src/api/socket/core/emitAuth.js +0 -106
- package/src/api/socket/core/getSeqID.js +0 -40
- package/src/api/socket/core/getTaskResponseData.js +0 -22
- package/src/api/socket/core/markDelivery.js +0 -12
- package/src/api/socket/core/parseDelta.js +0 -391
- package/src/api/socket/detail/buildStream.js +0 -208
- package/src/api/socket/detail/constants.js +0 -24
- package/src/api/socket/listenMqtt.js +0 -364
- package/src/api/socket/middleware/index.js +0 -216
- package/src/api/threads/getThreadHistory.js +0 -664
- package/src/api/threads/getThreadInfo.js +0 -438
- package/src/api/threads/getThreadList.js +0 -293
- package/src/api/threads/getThreadPictures.js +0 -78
- package/src/api/users/getUserID.js +0 -65
- package/src/api/users/getUserInfo.js +0 -327
- package/src/core/sendReqMqtt.js +0 -96
- package/src/database/models/index.js +0 -87
- package/src/database/models/thread.js +0 -45
- package/src/database/models/user.js +0 -46
- package/src/database/threadData.js +0 -98
- package/src/database/userData.js +0 -89
- package/src/utils/client.js +0 -320
- package/src/utils/format.js +0 -1115
- package/src/utils/request.js +0 -305
package/src/utils/headers.js
CHANGED
|
@@ -1,115 +1,230 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const { randomUserAgent, generateUserAgentByPersona } = require("./user-agents");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Strip characters that are illegal in HTTP header values:
|
|
7
|
+
* control chars (except HTAB), DEL, CR, LF, and stringified arrays.
|
|
8
|
+
* This prevents ERR_INVALID_CHAR crashes that expose bot-like behaviour.
|
|
9
|
+
*/
|
|
4
10
|
function sanitizeHeaderValue(value) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
if (value === null || value === undefined) return '';
|
|
12
|
+
let str = String(value);
|
|
13
|
+
|
|
14
|
+
// Detect accidentally stringified JS arrays like '["performAutoLogin"]'
|
|
15
|
+
if (str.trim().startsWith('[') && str.trim().endsWith(']')) {
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(str);
|
|
18
|
+
if (Array.isArray(parsed)) return '';
|
|
19
|
+
} catch (_) {}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Remove control chars (0x00-0x08, 0x0A-0x1F), DEL (0x7F), CR, LF, brackets
|
|
23
|
+
str = str.replace(/[\x00-\x08\x0A-\x1F\x7F\r\n\[\]]/g, '').trim();
|
|
24
|
+
return str;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function sanitizeHeaders(headers) {
|
|
28
|
+
const out = {};
|
|
29
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
30
|
+
if (!key || typeof key !== 'string') continue;
|
|
31
|
+
const cleanKey = key.replace(/[^\x21-\x7E]/g, '').trim();
|
|
32
|
+
if (!cleanKey) continue;
|
|
33
|
+
const cleanVal = sanitizeHeaderValue(value);
|
|
34
|
+
if (cleanVal !== '') {
|
|
35
|
+
out[cleanKey] = cleanVal;
|
|
36
|
+
}
|
|
20
37
|
}
|
|
21
|
-
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
22
40
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
const LOCALE_PROFILES = [
|
|
42
|
+
'en-US,en;q=0.9',
|
|
43
|
+
'en-GB,en;q=0.9,en-US;q=0.8',
|
|
44
|
+
'en-US,en;q=0.9,es;q=0.8',
|
|
45
|
+
'en-US,en;q=0.9,fr;q=0.8',
|
|
46
|
+
'en-CA,en;q=0.9,fr;q=0.8',
|
|
47
|
+
'en-AU,en;q=0.9,en-GB;q=0.8'
|
|
48
|
+
];
|
|
29
49
|
|
|
30
|
-
|
|
50
|
+
const TIMEZONE_OFFSETS = [-480, -420, -360, -300, -240, -180, -120, 0, 60, 120, 180, 240, 300, 360, 480, 540, 600];
|
|
51
|
+
|
|
52
|
+
function getRandomLocale() {
|
|
53
|
+
return LOCALE_PROFILES[Math.floor(Math.random() * LOCALE_PROFILES.length)];
|
|
31
54
|
}
|
|
32
55
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (!name || typeof name !== "string") return "";
|
|
36
|
-
// Remove invalid characters for HTTP header names
|
|
37
|
-
return name.replace(/[^\x21-\x7E]/g, "").trim();
|
|
56
|
+
function getRandomTimezone() {
|
|
57
|
+
return TIMEZONE_OFFSETS[Math.floor(Math.random() * TIMEZONE_OFFSETS.length)];
|
|
38
58
|
}
|
|
39
59
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
};
|
|
73
|
-
if (ctx?.region) {
|
|
74
|
-
const regionValue = sanitizeHeaderValue(ctx.region);
|
|
75
|
-
if (regionValue) headers["X-MSGR-Region"] = regionValue;
|
|
76
|
-
}
|
|
77
|
-
if (customHeader && typeof customHeader === "object") {
|
|
78
|
-
// Filter customHeader to only include valid HTTP header values (strings, numbers, booleans)
|
|
79
|
-
// Exclude functions, objects, arrays, and other non-serializable values
|
|
80
|
-
for (const [key, value] of Object.entries(customHeader)) {
|
|
81
|
-
// Skip null, undefined, functions, objects, and arrays
|
|
82
|
-
if (value === null || value === undefined || typeof value === "function") {
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (typeof value === "object") {
|
|
86
|
-
// Arrays are objects in JavaScript, so check for arrays explicitly
|
|
87
|
-
if (Array.isArray(value)) {
|
|
88
|
-
continue;
|
|
60
|
+
/**
|
|
61
|
+
* Generates a comprehensive and realistic set of headers for requests to Facebook.
|
|
62
|
+
* @param {string} url - The target URL.
|
|
63
|
+
* @param {object} options - Global options from context.
|
|
64
|
+
* @param {object} ctx - The application context (containing fb_dtsg, lsd, etc.).
|
|
65
|
+
* @param {object} customHeader - Any extra headers to merge.
|
|
66
|
+
* @param {string} requestType - Type of request: 'xhr' for GraphQL/AJAX or 'navigate' for page navigation
|
|
67
|
+
* @returns {object} A complete headers object.
|
|
68
|
+
*/
|
|
69
|
+
function getHeaders(url, options, ctx, customHeader, requestType = 'navigate') {
|
|
70
|
+
const persona = options?.persona || 'desktop';
|
|
71
|
+
const isAndroid = persona === 'android' || persona === 'mobile';
|
|
72
|
+
|
|
73
|
+
let userAgent, secChUa, secChUaFullVersionList, secChUaPlatform, secChUaPlatformVersion;
|
|
74
|
+
let androidData = null;
|
|
75
|
+
|
|
76
|
+
if (isAndroid) {
|
|
77
|
+
if (options && options.cachedAndroidUA) {
|
|
78
|
+
userAgent = options.cachedAndroidUA;
|
|
79
|
+
androidData = {
|
|
80
|
+
resolution: options.cachedAndroidResolution,
|
|
81
|
+
locale: options.cachedAndroidLocale,
|
|
82
|
+
device: options.cachedAndroidDevice
|
|
83
|
+
};
|
|
84
|
+
} else {
|
|
85
|
+
const generated = generateUserAgentByPersona('android', options);
|
|
86
|
+
userAgent = generated.userAgent;
|
|
87
|
+
androidData = {
|
|
88
|
+
resolution: generated.resolution,
|
|
89
|
+
locale: generated.locale,
|
|
90
|
+
device: generated.device
|
|
91
|
+
};
|
|
89
92
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
} else {
|
|
94
|
+
if (options && options.cachedUserAgent) {
|
|
95
|
+
userAgent = options.cachedUserAgent;
|
|
96
|
+
secChUa = options.cachedSecChUa;
|
|
97
|
+
secChUaFullVersionList = options.cachedSecChUaFullVersionList;
|
|
98
|
+
secChUaPlatform = options.cachedSecChUaPlatform;
|
|
99
|
+
secChUaPlatformVersion = options.cachedSecChUaPlatformVersion;
|
|
100
|
+
} else {
|
|
101
|
+
const generated = randomUserAgent();
|
|
102
|
+
userAgent = generated.userAgent;
|
|
103
|
+
secChUa = generated.secChUa;
|
|
104
|
+
secChUaFullVersionList = generated.secChUaFullVersionList;
|
|
105
|
+
secChUaPlatform = generated.secChUaPlatform;
|
|
106
|
+
secChUaPlatformVersion = generated.secChUaPlatformVersion;
|
|
99
107
|
}
|
|
100
|
-
}
|
|
101
108
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
|
|
110
|
+
const host = new URL(url).hostname;
|
|
111
|
+
const referer = `https://${host}/`;
|
|
112
|
+
|
|
113
|
+
const isXhr = requestType === 'xhr';
|
|
114
|
+
|
|
115
|
+
const locales = options?.cachedLocale || (androidData?.locale ? androidData.locale.replace('_', '-') : getRandomLocale());
|
|
116
|
+
const timezone = options?.cachedTimezone || getRandomTimezone();
|
|
117
|
+
|
|
118
|
+
if (isAndroid) {
|
|
119
|
+
const headers = {
|
|
120
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
121
|
+
'Host': host,
|
|
122
|
+
'Connection': 'keep-alive',
|
|
123
|
+
'User-Agent': userAgent,
|
|
124
|
+
'Accept': '*/*',
|
|
125
|
+
'Accept-Language': locales,
|
|
126
|
+
'Accept-Encoding': 'gzip, deflate',
|
|
127
|
+
'X-FB-HTTP-Engine': 'Liger'
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
if (androidData && androidData.resolution) {
|
|
131
|
+
headers['X-FB-Client-Density'] = String(androidData.resolution.density);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (ctx) {
|
|
135
|
+
if (ctx.lsd || ctx.fb_dtsg) {
|
|
136
|
+
headers['X-Fb-Lsd'] = ctx.lsd || ctx.fb_dtsg;
|
|
137
|
+
}
|
|
138
|
+
if (ctx.region) {
|
|
139
|
+
headers['X-MSGR-Region'] = ctx.region;
|
|
140
|
+
}
|
|
141
|
+
// Spin params are spread directly into ctx by buildAPI — ctx.master never exists.
|
|
142
|
+
if (ctx.__spin_r) headers['X-Fb-Spin-R'] = String(ctx.__spin_r);
|
|
143
|
+
if (ctx.__spin_b) headers['X-Fb-Spin-B'] = String(ctx.__spin_b);
|
|
144
|
+
if (ctx.__spin_t) headers['X-Fb-Spin-T'] = String(ctx.__spin_t);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (customHeader) {
|
|
148
|
+
Object.assign(headers, customHeader);
|
|
149
|
+
if (customHeader.noRef) {
|
|
150
|
+
delete headers.Referer;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return sanitizeHeaders(headers);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const isWindows = secChUaPlatform === '"Windows"';
|
|
158
|
+
const isMac = secChUaPlatform === '"macOS"';
|
|
159
|
+
const isLinux = secChUaPlatform === '"Linux"';
|
|
160
|
+
|
|
161
|
+
const headers = {
|
|
162
|
+
'Accept': isXhr ? '*/*' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
|
163
|
+
'Accept-Language': locales,
|
|
164
|
+
'Accept-Encoding': 'gzip, deflate, br',
|
|
165
|
+
'Cache-Control': 'no-cache',
|
|
166
|
+
'Connection': 'keep-alive',
|
|
167
|
+
'DNT': '1',
|
|
168
|
+
'Dpr': '1',
|
|
169
|
+
'Host': host,
|
|
170
|
+
'Pragma': 'no-cache',
|
|
171
|
+
'Referer': referer,
|
|
172
|
+
'Sec-Ch-Prefers-Color-Scheme': 'light',
|
|
173
|
+
'Sec-Ch-Ua': secChUa,
|
|
174
|
+
'Sec-Ch-Ua-Full-Version-List': secChUaFullVersionList,
|
|
175
|
+
'Sec-Ch-Ua-Mobile': '?0',
|
|
176
|
+
'Sec-Ch-Ua-Model': '""',
|
|
177
|
+
'Sec-Ch-Ua-Platform': secChUaPlatform,
|
|
178
|
+
'Sec-Ch-Ua-Platform-Version': secChUaPlatformVersion,
|
|
179
|
+
'Sec-Fetch-Dest': isXhr ? 'empty' : 'document',
|
|
180
|
+
'Sec-Fetch-Mode': isXhr ? 'cors' : 'navigate',
|
|
181
|
+
'Sec-Fetch-Site': isXhr ? 'same-origin' : 'none',
|
|
182
|
+
'User-Agent': userAgent,
|
|
183
|
+
'Viewport-Width': '1920',
|
|
184
|
+
'X-FB-Timezone-Offset': String(timezone * 60)
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
if (isWindows || isMac || isLinux) {
|
|
188
|
+
headers['Sec-Ch-Ua-Arch'] = '"x86"';
|
|
189
|
+
headers['Sec-Ch-Ua-Bitness'] = '"64"';
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (isXhr) {
|
|
193
|
+
headers['Origin'] = `https://${host}`;
|
|
194
|
+
headers['X-Requested-With'] = 'XMLHttpRequest';
|
|
195
|
+
} else {
|
|
196
|
+
headers['Sec-Fetch-User'] = '?1';
|
|
197
|
+
headers['Upgrade-Insecure-Requests'] = '1';
|
|
110
198
|
}
|
|
111
|
-
|
|
112
|
-
|
|
199
|
+
|
|
200
|
+
if (ctx) {
|
|
201
|
+
if (ctx.lsd || ctx.fb_dtsg) {
|
|
202
|
+
headers['X-Fb-Lsd'] = ctx.lsd || ctx.fb_dtsg;
|
|
203
|
+
}
|
|
204
|
+
if (ctx.region) {
|
|
205
|
+
headers['X-MSGR-Region'] = ctx.region;
|
|
206
|
+
}
|
|
207
|
+
// Spin params are spread directly into ctx by buildAPI — ctx.master never exists.
|
|
208
|
+
if (ctx.__spin_r) headers['X-Fb-Spin-R'] = String(ctx.__spin_r);
|
|
209
|
+
if (ctx.__spin_b) headers['X-Fb-Spin-B'] = String(ctx.__spin_b);
|
|
210
|
+
if (ctx.__spin_t) headers['X-Fb-Spin-T'] = String(ctx.__spin_t);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (customHeader) {
|
|
214
|
+
Object.assign(headers, customHeader);
|
|
215
|
+
if (customHeader.noRef) {
|
|
216
|
+
delete headers.Referer;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return sanitizeHeaders(headers);
|
|
113
221
|
}
|
|
114
222
|
|
|
115
|
-
|
|
223
|
+
const meta = (prop) => new RegExp(`<meta property="${prop}" content="([^"]*)"`);
|
|
224
|
+
|
|
225
|
+
module.exports = {
|
|
226
|
+
getHeaders,
|
|
227
|
+
meta,
|
|
228
|
+
getRandomLocale,
|
|
229
|
+
getRandomTimezone
|
|
230
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/* eslint-disable no-prototype-builtins */
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const cheerio = require("cheerio");
|
|
5
|
+
const util = require("util");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Fetches a URL, scrapes all <script type="application/json"> tags, and returns their parsed content.
|
|
9
|
+
* @param {string} url - The URL to fetch.
|
|
10
|
+
* @param {object} jar - The cookie jar.
|
|
11
|
+
* @param {object} qs - Query string parameters.
|
|
12
|
+
* @param {object} options - Global options.
|
|
13
|
+
* @param {object} ctx - The application context.
|
|
14
|
+
* @param {object} customHeader - Custom headers.
|
|
15
|
+
* @returns {Promise<Array<Object>>} A promise that resolves with an array of parsed JSON objects.
|
|
16
|
+
*/
|
|
17
|
+
async function json(url, jar, qs, options, ctx, customHeader) {
|
|
18
|
+
const network = require("./axios");
|
|
19
|
+
const constants = require("./constants");
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const res = await network.get(url, jar, qs, options, ctx, customHeader);
|
|
23
|
+
const body = res.body;
|
|
24
|
+
const $ = cheerio.load(body);
|
|
25
|
+
const scripts = $('script[type="application/json"]');
|
|
26
|
+
|
|
27
|
+
if (scripts.length === 0) {
|
|
28
|
+
constants.warn(`No <script type="application/json"> tags found on ${url}`);
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const allJsonData = [];
|
|
33
|
+
scripts.each((index, element) => {
|
|
34
|
+
try {
|
|
35
|
+
const jsonContent = $(element).html();
|
|
36
|
+
if (jsonContent) {
|
|
37
|
+
allJsonData.push(JSON.parse(jsonContent));
|
|
38
|
+
}
|
|
39
|
+
} catch (e) {
|
|
40
|
+
constants.warn(`Could not parse JSON from script #${index + 1} on ${url}`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return allJsonData;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
constants.error(`Error in utils.json fetching from ${url}:`, error);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates an object with pre-filled request defaults based on HTML and user context.
|
|
53
|
+
* @param {string} html - The HTML content.
|
|
54
|
+
* @param {string|number} userID - The user ID.
|
|
55
|
+
* @param {object} ctx - The context containing session data.
|
|
56
|
+
* @returns {object} An object with .get, .post, and .postFormData methods.
|
|
57
|
+
*/
|
|
58
|
+
function makeDefaults(html, userID, ctx) {
|
|
59
|
+
const network = require("./axios");
|
|
60
|
+
const constants = require("./constants");
|
|
61
|
+
|
|
62
|
+
let reqCounter = 1;
|
|
63
|
+
const revision = constants.getFrom(html, 'revision":', ",");
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Merges provided data with default request parameters.
|
|
67
|
+
* @param {object} obj - The original query or form object.
|
|
68
|
+
* @returns {object} The merged object.
|
|
69
|
+
*/
|
|
70
|
+
function mergeWithDefaults(obj) {
|
|
71
|
+
const newObj = {
|
|
72
|
+
av: userID,
|
|
73
|
+
__user: userID,
|
|
74
|
+
__req: (reqCounter++).toString(36),
|
|
75
|
+
__rev: revision,
|
|
76
|
+
__a: 1,
|
|
77
|
+
...(ctx && {
|
|
78
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
79
|
+
jazoest: ctx.jazoest,
|
|
80
|
+
}),
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
if (!obj) return newObj;
|
|
84
|
+
|
|
85
|
+
for (const prop in obj) {
|
|
86
|
+
if (obj.hasOwnProperty(prop) && !(prop in newObj)) {
|
|
87
|
+
newObj[prop] = obj[prop];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return newObj;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
/**
|
|
96
|
+
* Makes a GET request with merged defaults.
|
|
97
|
+
* @param {string} url
|
|
98
|
+
* @param {object} jar
|
|
99
|
+
* @param {object} qs
|
|
100
|
+
* @param {object} ctxx
|
|
101
|
+
* @param {object} [customHeader={}]
|
|
102
|
+
* @returns {Promise<object>}
|
|
103
|
+
*/
|
|
104
|
+
get: (url, jar, qs, ctxx, customHeader = {}) =>
|
|
105
|
+
network.get(url, jar, mergeWithDefaults(qs), ctx?.globalOptions, ctxx || ctx, customHeader),
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Makes a POST request with merged defaults.
|
|
109
|
+
* @param {string} url
|
|
110
|
+
* @param {object} jar
|
|
111
|
+
* @param {object} form
|
|
112
|
+
* @param {object} ctxx
|
|
113
|
+
* @param {object} [customHeader={}]
|
|
114
|
+
* @returns {Promise<object>}
|
|
115
|
+
*/
|
|
116
|
+
post: (url, jar, form, ctxx, customHeader = {}) =>
|
|
117
|
+
network.post(url, jar, mergeWithDefaults(form), ctx?.globalOptions, ctxx || ctx, customHeader),
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Makes a multipart/form-data POST request with merged defaults.
|
|
121
|
+
* @param {string} url
|
|
122
|
+
* @param {object} jar
|
|
123
|
+
* @param {object} form
|
|
124
|
+
* @param {object} qs
|
|
125
|
+
* @param {object} ctxx
|
|
126
|
+
* @returns {Promise<object>}
|
|
127
|
+
*/
|
|
128
|
+
postFormData: (url, jar, form, qs, ctxx) =>
|
|
129
|
+
network.postFormData(
|
|
130
|
+
url,
|
|
131
|
+
jar,
|
|
132
|
+
mergeWithDefaults(form),
|
|
133
|
+
mergeWithDefaults(qs),
|
|
134
|
+
ctx?.globalOptions,
|
|
135
|
+
ctxx || ctx
|
|
136
|
+
),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = {
|
|
141
|
+
...require('./axios'),
|
|
142
|
+
...require('./clients'),
|
|
143
|
+
...require('./constants'),
|
|
144
|
+
...require('./formatters'),
|
|
145
|
+
...require('./headers'),
|
|
146
|
+
...require('./user-agents'),
|
|
147
|
+
...require('./antiSuspension'),
|
|
148
|
+
...require('./rateLimiter'),
|
|
149
|
+
json,
|
|
150
|
+
makeDefaults,
|
|
151
|
+
promisify: (func) => util.promisify(func),
|
|
152
|
+
delay: (ms) => new Promise(r => setTimeout(r, ms))
|
|
153
|
+
};
|