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,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const utils = require('./index');
|
|
4
|
+
|
|
5
|
+
class AutoReLoginManager {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.credentials = null;
|
|
8
|
+
this.loginOptions = null;
|
|
9
|
+
this.loginCallback = null;
|
|
10
|
+
this.isReLoggingIn = false;
|
|
11
|
+
this.pendingRequests = [];
|
|
12
|
+
this.maxRetries = 3;
|
|
13
|
+
this.retryCount = 0;
|
|
14
|
+
this.onReLoginSuccess = null;
|
|
15
|
+
this.onReLoginFailure = null;
|
|
16
|
+
this.enabled = false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
setCredentials(credentials, options, callback) {
|
|
20
|
+
this.credentials = credentials;
|
|
21
|
+
this.loginOptions = options || {};
|
|
22
|
+
this.loginCallback = callback;
|
|
23
|
+
this.enabled = true;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
isEnabled() {
|
|
27
|
+
return this.enabled && this.credentials !== null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async handleSessionExpiry(api, fbLink, ERROR_RETRIEVING) {
|
|
31
|
+
if (!this.isEnabled()) {
|
|
32
|
+
utils.warn("AutoReLogin", "Auto re-login not enabled. Credentials not stored.");
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (this.isReLoggingIn) {
|
|
37
|
+
utils.log("AutoReLogin", "Re-login already in progress. Queuing request...");
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
this.pendingRequests.push({ resolve, reject });
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (this.retryCount >= this.maxRetries) {
|
|
44
|
+
utils.error("AutoReLogin", `Maximum re-login attempts (${this.maxRetries}) exceeded`);
|
|
45
|
+
if (this.onReLoginFailure) {
|
|
46
|
+
this.onReLoginFailure(new Error("Max re-login retries exceeded"));
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.isReLoggingIn = true;
|
|
52
|
+
this.retryCount++;
|
|
53
|
+
utils.log("AutoReLogin", `Starting automatic re-login (attempt ${this.retryCount}/${this.maxRetries})...`);
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
await this.pauseAPIRequests();
|
|
57
|
+
|
|
58
|
+
const loginHelperModel = require('../engine/models/loginHelper');
|
|
59
|
+
const setOptionsModel = require('../engine/models/setOptions');
|
|
60
|
+
const buildAPIModel = require('../engine/models/buildAPI');
|
|
61
|
+
|
|
62
|
+
await new Promise((resolve, reject) => {
|
|
63
|
+
loginHelperModel(
|
|
64
|
+
this.credentials,
|
|
65
|
+
this.loginOptions,
|
|
66
|
+
(loginError, newApi) => {
|
|
67
|
+
if (loginError) {
|
|
68
|
+
reject(loginError);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (api) {
|
|
73
|
+
api.ctx = newApi.ctx;
|
|
74
|
+
api.defaultFuncs = newApi.defaultFuncs;
|
|
75
|
+
|
|
76
|
+
if (api.tokenRefreshManager) {
|
|
77
|
+
api.tokenRefreshManager.resetFailureCount();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
resolve(newApi);
|
|
82
|
+
},
|
|
83
|
+
setOptionsModel,
|
|
84
|
+
buildAPIModel,
|
|
85
|
+
api,
|
|
86
|
+
fbLink,
|
|
87
|
+
ERROR_RETRIEVING
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
utils.log("AutoReLogin", "Re-login successful! Session restored.");
|
|
92
|
+
this.retryCount = 0;
|
|
93
|
+
this.isReLoggingIn = false;
|
|
94
|
+
|
|
95
|
+
this.resolvePendingRequests(true);
|
|
96
|
+
|
|
97
|
+
if (this.onReLoginSuccess) {
|
|
98
|
+
this.onReLoginSuccess();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return true;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
utils.error("AutoReLogin", `Re-login failed:`, error.message);
|
|
104
|
+
this.isReLoggingIn = false;
|
|
105
|
+
|
|
106
|
+
if (this.retryCount >= this.maxRetries) {
|
|
107
|
+
this.resolvePendingRequests(false);
|
|
108
|
+
if (this.onReLoginFailure) {
|
|
109
|
+
this.onReLoginFailure(error);
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const backoffDelay = Math.min(30000, Math.pow(2, this.retryCount) * 1000);
|
|
115
|
+
utils.log("AutoReLogin", `Retrying re-login in ${backoffDelay}ms...`);
|
|
116
|
+
await new Promise(resolve => setTimeout(resolve, backoffDelay));
|
|
117
|
+
|
|
118
|
+
return await this.handleSessionExpiry(api, fbLink, ERROR_RETRIEVING);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async pauseAPIRequests() {
|
|
123
|
+
utils.log("AutoReLogin", "Pausing API requests during re-login...");
|
|
124
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
resolvePendingRequests(success) {
|
|
128
|
+
utils.log("AutoReLogin", `Resolving ${this.pendingRequests.length} pending requests (success: ${success})`);
|
|
129
|
+
|
|
130
|
+
this.pendingRequests.forEach(({ resolve, reject }) => {
|
|
131
|
+
if (success) {
|
|
132
|
+
resolve(true);
|
|
133
|
+
} else {
|
|
134
|
+
reject(new Error("Re-login failed"));
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
this.pendingRequests = [];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
setReLoginSuccessCallback(callback) {
|
|
142
|
+
this.onReLoginSuccess = callback;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
setReLoginFailureCallback(callback) {
|
|
146
|
+
this.onReLoginFailure = callback;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
disable() {
|
|
150
|
+
this.enabled = false;
|
|
151
|
+
this.credentials = null;
|
|
152
|
+
this.loginOptions = null;
|
|
153
|
+
this.loginCallback = null;
|
|
154
|
+
utils.log("AutoReLogin", "Auto re-login disabled and credentials cleared");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
reset() {
|
|
158
|
+
this.retryCount = 0;
|
|
159
|
+
this.isReLoggingIn = false;
|
|
160
|
+
this.pendingRequests = [];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const globalAutoReLoginManager = new AutoReLoginManager();
|
|
165
|
+
|
|
166
|
+
module.exports = {
|
|
167
|
+
AutoReLoginManager,
|
|
168
|
+
globalAutoReLoginManager
|
|
169
|
+
};
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/* eslint-disable no-prototype-builtins */
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const axios = require("axios");
|
|
5
|
+
const { CookieJar } = require("tough-cookie");
|
|
6
|
+
const { wrapper } = require("axios-cookiejar-support");
|
|
7
|
+
const FormData = require("form-data");
|
|
8
|
+
const { getHeaders } = require("./headers");
|
|
9
|
+
const { getType } = require("./constants");
|
|
10
|
+
const { globalRateLimiter } = require("./rateLimiter");
|
|
11
|
+
|
|
12
|
+
const jar = new CookieJar();
|
|
13
|
+
const client = wrapper(axios.create({ jar }));
|
|
14
|
+
|
|
15
|
+
let proxyConfig = {};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A utility to introduce a delay, used for retries.
|
|
19
|
+
* @param {number} ms - The delay in milliseconds.
|
|
20
|
+
* @returns {Promise<void>}
|
|
21
|
+
*/
|
|
22
|
+
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Adapts the axios response/error to match the structure expected by the rest of the application.
|
|
26
|
+
* @param {object} res - The axios response or error object.
|
|
27
|
+
* @returns {object} An object that mimics the old 'request' library's response.
|
|
28
|
+
*/
|
|
29
|
+
function adaptResponse(res) {
|
|
30
|
+
const response = res.response || res;
|
|
31
|
+
return {
|
|
32
|
+
...response,
|
|
33
|
+
body: response.data,
|
|
34
|
+
statusCode: response.status,
|
|
35
|
+
request: {
|
|
36
|
+
uri: new URL(response.config.url),
|
|
37
|
+
headers: response.config.headers,
|
|
38
|
+
method: response.config.method.toUpperCase(),
|
|
39
|
+
form: response.config.data,
|
|
40
|
+
formData: response.config.data
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Performs a request with retry logic and exponential backoff.
|
|
47
|
+
* @param {Function} requestFunction - A function that returns an axios promise.
|
|
48
|
+
* @param {number} [retries=3] - The number of retries.
|
|
49
|
+
* @param {string} [endpoint=''] - Endpoint identifier for rate limiting.
|
|
50
|
+
* @param {string} [threadID=''] - Thread identifier for rate limiting.
|
|
51
|
+
* @returns {Promise<object>}
|
|
52
|
+
*/
|
|
53
|
+
async function requestWithRetry(requestFunction, retries = 3, endpoint = '', threadID = '') {
|
|
54
|
+
await globalRateLimiter.checkRateLimit();
|
|
55
|
+
|
|
56
|
+
if (endpoint && globalRateLimiter.isEndpointOnCooldown(endpoint)) {
|
|
57
|
+
const cooldown = globalRateLimiter.getEndpointCooldownRemaining(endpoint);
|
|
58
|
+
console.warn(`Endpoint ${endpoint} on cooldown. Waiting ${cooldown}ms...`);
|
|
59
|
+
await delay(cooldown);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (threadID && globalRateLimiter.isThreadOnCooldown(threadID)) {
|
|
63
|
+
const cooldown = globalRateLimiter.getCooldownRemaining(threadID);
|
|
64
|
+
console.warn(`Thread ${threadID} on cooldown. Waiting ${cooldown}ms...`);
|
|
65
|
+
await delay(cooldown);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const checkAndApplyRateLimitCooldowns = (responseBody) => {
|
|
69
|
+
const ERROR_COOLDOWNS = {
|
|
70
|
+
1545012: 60000,
|
|
71
|
+
1675004: 30000,
|
|
72
|
+
368: 90000
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const applyCooldown = (errorCode) => {
|
|
76
|
+
if (errorCode && ERROR_COOLDOWNS[errorCode]) {
|
|
77
|
+
if (threadID) {
|
|
78
|
+
globalRateLimiter.setThreadCooldown(threadID, ERROR_COOLDOWNS[errorCode]);
|
|
79
|
+
}
|
|
80
|
+
if (endpoint) {
|
|
81
|
+
globalRateLimiter.setEndpointCooldown(endpoint, ERROR_COOLDOWNS[errorCode]);
|
|
82
|
+
}
|
|
83
|
+
console.warn(`Rate limit detected (error ${errorCode}). Applied cooldown.`);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
if (!responseBody || typeof responseBody !== 'object') {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (applyCooldown(responseBody.error)) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (Array.isArray(responseBody)) {
|
|
98
|
+
for (const item of responseBody) {
|
|
99
|
+
if (item && typeof item === 'object') {
|
|
100
|
+
if (applyCooldown(item.error)) return true;
|
|
101
|
+
if (item.errors && Array.isArray(item.errors)) {
|
|
102
|
+
for (const err of item.errors) {
|
|
103
|
+
const code = err.code || err.extensions?.code;
|
|
104
|
+
if (applyCooldown(code)) return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (responseBody.errors && Array.isArray(responseBody.errors)) {
|
|
112
|
+
for (const err of responseBody.errors) {
|
|
113
|
+
const code = err.code || err.extensions?.code;
|
|
114
|
+
if (applyCooldown(code)) return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return false;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < retries; i++) {
|
|
122
|
+
try {
|
|
123
|
+
const res = await requestFunction();
|
|
124
|
+
const adapted = adaptResponse(res);
|
|
125
|
+
|
|
126
|
+
checkAndApplyRateLimitCooldowns(adapted.body);
|
|
127
|
+
|
|
128
|
+
return adapted;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (error.response) {
|
|
131
|
+
const adapted = adaptResponse(error.response);
|
|
132
|
+
checkAndApplyRateLimitCooldowns(adapted.body);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (i === retries - 1) {
|
|
136
|
+
console.error(`Request failed after ${retries} attempts:`, error.message);
|
|
137
|
+
if (error.response) {
|
|
138
|
+
return adaptResponse(error.response);
|
|
139
|
+
}
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
const backoffTime = (1 << i) * 1000 + Math.floor(Math.random() * 200);
|
|
143
|
+
console.warn(`Request attempt ${i + 1} failed. Retrying in ${backoffTime}ms...`);
|
|
144
|
+
await delay(backoffTime);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Sets a proxy for all subsequent requests.
|
|
151
|
+
* @param {string} proxyUrl - The proxy URL (e.g., "http://user:pass@host:port").
|
|
152
|
+
*/
|
|
153
|
+
function setProxy(proxyUrl) {
|
|
154
|
+
if (proxyUrl) {
|
|
155
|
+
try {
|
|
156
|
+
const parsedProxy = new URL(proxyUrl);
|
|
157
|
+
proxyConfig = {
|
|
158
|
+
proxy: {
|
|
159
|
+
host: parsedProxy.hostname,
|
|
160
|
+
port: parsedProxy.port,
|
|
161
|
+
protocol: parsedProxy.protocol.replace(":", ""),
|
|
162
|
+
auth: parsedProxy.username && parsedProxy.password ? {
|
|
163
|
+
username: parsedProxy.username,
|
|
164
|
+
password: parsedProxy.password,
|
|
165
|
+
} : undefined,
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
} catch (e) {
|
|
169
|
+
console.error("Invalid proxy URL. Please use a full URL format (e.g., http://user:pass@host:port).");
|
|
170
|
+
proxyConfig = {};
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
proxyConfig = {};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* A simple GET request without extra options.
|
|
179
|
+
* @param {string} url - The URL to fetch.
|
|
180
|
+
* @returns {Promise<object>} A promise that resolves with the response.
|
|
181
|
+
*/
|
|
182
|
+
function cleanGet(url) {
|
|
183
|
+
const fn = () => client.get(url, { timeout: 60000, ...proxyConfig });
|
|
184
|
+
return requestWithRetry(fn);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Performs a GET request with query parameters and custom options.
|
|
189
|
+
* @param {string} url
|
|
190
|
+
* @param {object} reqJar
|
|
191
|
+
* @param {object} qs - Query string parameters.
|
|
192
|
+
* @param {object} options
|
|
193
|
+
* @param {object} ctx
|
|
194
|
+
* @param {object} customHeader
|
|
195
|
+
* @returns {Promise<object>}
|
|
196
|
+
*/
|
|
197
|
+
async function get(url, reqJar, qs, options, ctx, customHeader) {
|
|
198
|
+
const config = {
|
|
199
|
+
headers: getHeaders(url, options, ctx, customHeader),
|
|
200
|
+
timeout: 60000,
|
|
201
|
+
params: qs,
|
|
202
|
+
...proxyConfig,
|
|
203
|
+
validateStatus: (status) => status >= 200 && status < 600,
|
|
204
|
+
};
|
|
205
|
+
const endpoint = new URL(url).pathname;
|
|
206
|
+
return requestWithRetry(async () => await client.get(url, config), 3, endpoint);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Performs a POST request, automatically handling JSON or URL-encoded form data.
|
|
211
|
+
* @param {string} url
|
|
212
|
+
* @param {object} reqJar
|
|
213
|
+
* @param {object} form - The form data object.
|
|
214
|
+
* @param {object} options
|
|
215
|
+
* @param {object} ctx
|
|
216
|
+
* @param {object} customHeader
|
|
217
|
+
* @returns {Promise<object>}
|
|
218
|
+
*/
|
|
219
|
+
async function post(url, reqJar, form, options, ctx, customHeader) {
|
|
220
|
+
const headers = getHeaders(url, options, ctx, customHeader, 'xhr');
|
|
221
|
+
let data = form;
|
|
222
|
+
let contentType = headers['Content-Type'] || 'application/x-www-form-urlencoded';
|
|
223
|
+
|
|
224
|
+
if (contentType.includes('json')) {
|
|
225
|
+
data = JSON.stringify(form);
|
|
226
|
+
} else {
|
|
227
|
+
const transformedForm = new URLSearchParams();
|
|
228
|
+
for (const key in form) {
|
|
229
|
+
if (form.hasOwnProperty(key)) {
|
|
230
|
+
let value = form[key];
|
|
231
|
+
if (getType(value) === "Object") {
|
|
232
|
+
value = JSON.stringify(value);
|
|
233
|
+
}
|
|
234
|
+
transformedForm.append(key, value);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
data = transformedForm.toString();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
headers['Content-Type'] = contentType;
|
|
241
|
+
|
|
242
|
+
const config = {
|
|
243
|
+
headers,
|
|
244
|
+
timeout: 60000,
|
|
245
|
+
...proxyConfig,
|
|
246
|
+
validateStatus: (status) => status >= 200 && status < 600,
|
|
247
|
+
};
|
|
248
|
+
const endpoint = new URL(url).pathname;
|
|
249
|
+
return requestWithRetry(async () => await client.post(url, data, config), 3, endpoint);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Performs a POST request with multipart/form-data.
|
|
254
|
+
* @param {string} url
|
|
255
|
+
* @param {object} reqJar
|
|
256
|
+
* @param {object} form - The form data object, may contain readable streams.
|
|
257
|
+
* @param {object} qs - Query string parameters.
|
|
258
|
+
* @param {object} options
|
|
259
|
+
* @param {object} ctx
|
|
260
|
+
* @returns {Promise<object>}
|
|
261
|
+
*/
|
|
262
|
+
async function postFormData(url, reqJar, form, qs, options, ctx) {
|
|
263
|
+
const formData = new FormData();
|
|
264
|
+
for (const key in form) {
|
|
265
|
+
if (form.hasOwnProperty(key)) {
|
|
266
|
+
formData.append(key, form[key]);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const customHeader = { "Content-Type": `multipart/form-data; boundary=${formData.getBoundary()}` };
|
|
271
|
+
|
|
272
|
+
const config = {
|
|
273
|
+
headers: getHeaders(url, options, ctx, customHeader, 'xhr'),
|
|
274
|
+
timeout: 60000,
|
|
275
|
+
params: qs,
|
|
276
|
+
...proxyConfig,
|
|
277
|
+
validateStatus: (status) => status >= 200 && status < 600,
|
|
278
|
+
};
|
|
279
|
+
const endpoint = new URL(url).pathname;
|
|
280
|
+
return requestWithRetry(async () => await client.post(url, formData, config), 3, endpoint);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
module.exports = {
|
|
284
|
+
cleanGet,
|
|
285
|
+
get,
|
|
286
|
+
post,
|
|
287
|
+
postFormData,
|
|
288
|
+
getJar: () => jar,
|
|
289
|
+
setProxy,
|
|
290
|
+
};
|