@cexy/hoonfca 1.0.0 → 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/LICENSE +3 -0
- package/README.md +451 -43
- package/examples/login-with-cookies.js +102 -0
- package/examples/verify.js +70 -0
- package/index.js +1 -466
- package/package.json +98 -6
- 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/{changeThreadEmoji.js → apis/changeThreadEmoji.js} +7 -8
- 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/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 +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/apis/markAsRead.js +99 -0
- 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 -0
- 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 +230 -0
- 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/replit.nix +0 -3
- package/src/addExternalModule.js +0 -25
- package/src/addUserToGroup.js +0 -98
- package/src/changeAdminStatus.js +0 -98
- package/src/changeArchivedStatus.js +0 -51
- package/src/changeAvatar.js +0 -89
- package/src/changeBio.js +0 -74
- package/src/changeBlockedStatus.js +0 -45
- package/src/changeBlockedStatusMqtt.js +0 -65
- package/src/changeCover.js +0 -92
- package/src/changeGroupImage.js +0 -110
- package/src/changeName.js +0 -106
- package/src/changeNickname.js +0 -58
- package/src/changeThreadColor.js +0 -62
- package/src/changeUsername.js +0 -80
- package/src/createCommentPost.js +0 -196
- package/src/createNewGroup.js +0 -81
- package/src/createPoll.js +0 -64
- package/src/createPost.js +0 -285
- package/src/data/getThreadInfo.json +0 -1
- package/src/deleteMessage.js +0 -55
- package/src/deleteThread.js +0 -55
- package/src/editMessage.js +0 -66
- package/src/follow.js +0 -71
- package/src/forwardAttachment.js +0 -57
- package/src/getAccess.js +0 -130
- package/src/getAvatarUser.js +0 -88
- package/src/getBotInitialData.js +0 -59
- package/src/getCtx.js +0 -5
- package/src/getCurrentUserID.js +0 -5
- package/src/getEmojiUrl.js +0 -18
- package/src/getFriendsList.js +0 -81
- package/src/getMessage.js +0 -827
- package/src/getOptions.js +0 -5
- package/src/getRegion.js +0 -7
- package/src/getThreadHistory.js +0 -496
- package/src/getThreadHistoryDeprecated.js +0 -95
- package/src/getThreadInfo.js +0 -194
- package/src/getThreadInfoDeprecated.js +0 -77
- package/src/getThreadList.js +0 -219
- package/src/getThreadListDeprecated.js +0 -86
- package/src/getThreadPictures.js +0 -85
- package/src/getUserID.js +0 -67
- package/src/getUserInfo.js +0 -89
- package/src/handleFriendRequest.js +0 -56
- package/src/handleMessageRequest.js +0 -65
- package/src/httpGet.js +0 -53
- package/src/httpPost.js +0 -53
- package/src/httpPostFormData.js +0 -58
- package/src/listenMqtt.js +0 -683
- package/src/listenNotification.js +0 -96
- package/src/logout.js +0 -77
- package/src/markAsDelivered.js +0 -53
- package/src/markAsRead.js +0 -74
- package/src/markAsReadAll.js +0 -46
- package/src/markAsSeen.js +0 -57
- package/src/muteThread.js +0 -49
- package/src/pinMessage.js +0 -60
- package/src/refreshFb_dtsg.js +0 -75
- package/src/removeUserFromGroup.js +0 -59
- package/src/resolvePhotoUrl.js +0 -47
- package/src/searchForThread.js +0 -55
- package/src/searchStickers.js +0 -59
- package/src/sendMessage.js +0 -444
- package/src/sendMessageMqtt.js +0 -326
- package/src/sendTypingIndicator.js +0 -54
- package/src/setMessageReaction.js +0 -126
- package/src/setMessageReactionMqtt.js +0 -74
- package/src/setPostReaction.js +0 -103
- package/src/setProfileGuard.js +0 -66
- package/src/setStoryReaction.js +0 -97
- package/src/setTitle.js +0 -100
- package/src/shareContact.js +0 -101
- package/src/shareLink.js +0 -105
- package/src/stopListenMqtt.js +0 -47
- package/src/threadColors.js +0 -119
- package/src/unfriend.js +0 -58
- package/src/unsendMessage.js +0 -51
- package/src/uploadAttachment.js +0 -98
- package/utils.js +0 -919
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const { getRandom } = require("./constants");
|
|
3
|
+
|
|
4
|
+
const BROWSER_DATA = {
|
|
5
|
+
windows: {
|
|
6
|
+
platform: "Windows NT 10.0; Win64; x64",
|
|
7
|
+
chromeVersions: ["139.0.0.0", "131.0.6778.86", "130.0.6723.92", "129.0.6668.101", "128.0.6613.120", "127.0.6533.120"],
|
|
8
|
+
edgeVersions: ["139.0.0.0", "131.0.2903.51", "130.0.2849.68", "129.0.2792.89"],
|
|
9
|
+
platformVersion: '"15.0.0"'
|
|
10
|
+
},
|
|
11
|
+
mac: {
|
|
12
|
+
platform: "Macintosh; Intel Mac OS X 10_15_7",
|
|
13
|
+
chromeVersions: ["139.0.0.0", "131.0.6778.86", "130.0.6723.92", "129.0.6668.101", "128.0.6613.120", "127.0.6533.120"],
|
|
14
|
+
edgeVersions: ["139.0.0.0", "131.0.2903.51", "130.0.2849.68", "129.0.2792.89"],
|
|
15
|
+
platformVersion: '"14.7.0"'
|
|
16
|
+
},
|
|
17
|
+
linux: {
|
|
18
|
+
platform: "X11; Linux x86_64",
|
|
19
|
+
chromeVersions: ["139.0.0.0", "131.0.6778.86", "130.0.6723.92", "129.0.6668.101", "128.0.6613.120"],
|
|
20
|
+
edgeVersions: ["139.0.0.0", "131.0.2903.51", "130.0.2849.68"],
|
|
21
|
+
platformVersion: '""'
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const defaultUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Generates a realistic, randomized User-Agent string and related Sec-CH headers.
|
|
29
|
+
* Supports Chrome and Edge browsers across Windows, macOS, and Linux.
|
|
30
|
+
* @returns {{userAgent: string, secChUa: string, secChUaFullVersionList: string, secChUaPlatform: string, secChUaPlatformVersion: string, browser: string}}
|
|
31
|
+
*/
|
|
32
|
+
function randomUserAgent() {
|
|
33
|
+
const os = getRandom(Object.keys(BROWSER_DATA));
|
|
34
|
+
const data = BROWSER_DATA[os];
|
|
35
|
+
|
|
36
|
+
const useEdge = Math.random() > 0.7 && data.edgeVersions;
|
|
37
|
+
const versions = useEdge ? data.edgeVersions : data.chromeVersions;
|
|
38
|
+
const version = getRandom(versions);
|
|
39
|
+
const majorVersion = version.split('.')[0];
|
|
40
|
+
const browserName = useEdge ? 'Microsoft Edge' : 'Google Chrome';
|
|
41
|
+
const browserIdentifier = useEdge ? 'Edg' : 'Chrome';
|
|
42
|
+
|
|
43
|
+
const userAgent = useEdge
|
|
44
|
+
? `Mozilla/5.0 (${data.platform}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version} Safari/537.36 Edg/${version}`
|
|
45
|
+
: `Mozilla/5.0 (${data.platform}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version} Safari/537.36`;
|
|
46
|
+
|
|
47
|
+
const greeseValue = Math.random() > 0.5 ? '99' : '8';
|
|
48
|
+
const brands = useEdge ? [
|
|
49
|
+
`"Chromium";v="${majorVersion}"`,
|
|
50
|
+
`"Not(A:Brand";v="${greeseValue}"`,
|
|
51
|
+
`"${browserName}";v="${majorVersion}"`
|
|
52
|
+
] : [
|
|
53
|
+
`"${browserName}";v="${majorVersion}"`,
|
|
54
|
+
`"Not;A=Brand";v="${greeseValue}"`,
|
|
55
|
+
`"Chromium";v="${majorVersion}"`
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
const secChUa = brands.join(', ');
|
|
59
|
+
const secChUaFullVersionList = brands.map(b => {
|
|
60
|
+
const match = b.match(/v="(\d+)"/);
|
|
61
|
+
if (match && match[1] === majorVersion) {
|
|
62
|
+
return b.replace(`v="${majorVersion}"`, `v="${version}"`);
|
|
63
|
+
}
|
|
64
|
+
return b;
|
|
65
|
+
}).join(', ');
|
|
66
|
+
|
|
67
|
+
const platformName = os === 'windows' ? 'Windows' : os === 'mac' ? 'macOS' : 'Linux';
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
userAgent,
|
|
71
|
+
secChUa,
|
|
72
|
+
secChUaFullVersionList,
|
|
73
|
+
secChUaPlatform: `"${platformName}"`,
|
|
74
|
+
secChUaPlatformVersion: data.platformVersion,
|
|
75
|
+
browser: browserName
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function randomInt(min, max) {
|
|
80
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function randomChoice(arr) {
|
|
84
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function randomBuildId() {
|
|
88
|
+
const prefixes = ["QP1A", "RP1A", "SP1A", "TP1A", "UP1A", "AP4A"];
|
|
89
|
+
return `${randomChoice(prefixes)}.${randomInt(180000, 250000)}.${randomInt(10, 99)}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function randomResolution() {
|
|
93
|
+
const presets = [
|
|
94
|
+
{ width: 720, height: 1280, density: 2.0 },
|
|
95
|
+
{ width: 1080, height: 1920, density: 2.625 },
|
|
96
|
+
{ width: 1080, height: 2400, density: 3.0 },
|
|
97
|
+
{ width: 1440, height: 3040, density: 3.5 },
|
|
98
|
+
{ width: 1440, height: 3200, density: 4.0 }
|
|
99
|
+
];
|
|
100
|
+
return randomChoice(presets);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function randomFbav() {
|
|
104
|
+
return `${randomInt(390, 499)}.${randomInt(0, 3)}.${randomInt(0, 2)}.${randomInt(10, 60)}.${randomInt(100, 999)}`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function randomOrcaUA() {
|
|
108
|
+
const androidVersions = ["8.1.0", "9", "10", "11", "12", "13", "14"];
|
|
109
|
+
const devices = [
|
|
110
|
+
{ brand: "samsung", model: "SM-G996B" },
|
|
111
|
+
{ brand: "samsung", model: "SM-S908E" },
|
|
112
|
+
{ brand: "Xiaomi", model: "M2101K9AG" },
|
|
113
|
+
{ brand: "OPPO", model: "CPH2219" },
|
|
114
|
+
{ brand: "vivo", model: "V2109" },
|
|
115
|
+
{ brand: "HUAWEI", model: "VOG-L29" },
|
|
116
|
+
{ brand: "asus", model: "ASUS_I001DA" },
|
|
117
|
+
{ brand: "Google", model: "Pixel 6" },
|
|
118
|
+
{ brand: "realme", model: "RMX2170" }
|
|
119
|
+
];
|
|
120
|
+
const carriers = [
|
|
121
|
+
"Viettel Telecom", "Mobifone", "Vinaphone",
|
|
122
|
+
"T-Mobile", "Verizon", "AT&T",
|
|
123
|
+
"Telkomsel", "Jio", "NTT DOCOMO",
|
|
124
|
+
"Vodafone", "Orange"
|
|
125
|
+
];
|
|
126
|
+
const locales = [
|
|
127
|
+
"vi_VN", "en_US", "en_GB", "id_ID",
|
|
128
|
+
"th_TH", "fr_FR", "de_DE", "es_ES", "pt_BR"
|
|
129
|
+
];
|
|
130
|
+
const archs = ["arm64-v8a", "armeabi-v7a"];
|
|
131
|
+
|
|
132
|
+
const androidVersion = randomChoice(androidVersions);
|
|
133
|
+
const device = randomChoice(devices);
|
|
134
|
+
const buildId = randomBuildId();
|
|
135
|
+
const resolution = randomResolution();
|
|
136
|
+
const fbav = randomFbav();
|
|
137
|
+
const fbbv = randomInt(320000000, 520000000);
|
|
138
|
+
const arch = `${randomChoice(archs)}:${randomChoice(archs)}`;
|
|
139
|
+
const selectedLocale = randomChoice(locales);
|
|
140
|
+
const selectedCarrier = randomChoice(carriers);
|
|
141
|
+
|
|
142
|
+
const userAgent = `Dalvik/2.1.0 (Linux; U; Android ${androidVersion}; ${device.model} Build/${buildId}) ` +
|
|
143
|
+
`[FBAN/Orca-Android;FBAV/${fbav};FBPN/com.facebook.orca;` +
|
|
144
|
+
`FBLC/${selectedLocale};FBBV/${fbbv};FBCR/${selectedCarrier};` +
|
|
145
|
+
`FBMF/${device.brand};FBBD/${device.brand};FBDV/${device.model};` +
|
|
146
|
+
`FBSV/${androidVersion};FBCA/${arch};` +
|
|
147
|
+
`FBDM/{density=${resolution.density.toFixed(1)},width=${resolution.width},height=${resolution.height}};` +
|
|
148
|
+
`FB_FW/1;]`;
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
userAgent,
|
|
152
|
+
androidVersion,
|
|
153
|
+
device,
|
|
154
|
+
buildId,
|
|
155
|
+
resolution,
|
|
156
|
+
fbav,
|
|
157
|
+
fbbv,
|
|
158
|
+
locale: selectedLocale,
|
|
159
|
+
carrier: selectedCarrier
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function generateUserAgentByPersona(persona = 'desktop', options = {}) {
|
|
164
|
+
if (persona === 'android' || persona === 'mobile') {
|
|
165
|
+
if (options.cachedAndroidUA && options.cachedAndroidDevice) {
|
|
166
|
+
return {
|
|
167
|
+
userAgent: options.cachedAndroidUA,
|
|
168
|
+
androidVersion: options.cachedAndroidVersion,
|
|
169
|
+
device: options.cachedAndroidDevice,
|
|
170
|
+
buildId: options.cachedAndroidBuildId,
|
|
171
|
+
resolution: options.cachedAndroidResolution,
|
|
172
|
+
fbav: options.cachedAndroidFbav,
|
|
173
|
+
fbbv: options.cachedAndroidFbbv,
|
|
174
|
+
locale: options.cachedAndroidLocale,
|
|
175
|
+
carrier: options.cachedAndroidCarrier,
|
|
176
|
+
persona: 'android'
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const androidData = randomOrcaUA();
|
|
181
|
+
return {
|
|
182
|
+
...androidData,
|
|
183
|
+
persona: 'android'
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (options.cachedUserAgent && options.cachedSecChUa) {
|
|
188
|
+
return {
|
|
189
|
+
userAgent: options.cachedUserAgent,
|
|
190
|
+
secChUa: options.cachedSecChUa,
|
|
191
|
+
secChUaFullVersionList: options.cachedSecChUaFullVersionList,
|
|
192
|
+
secChUaPlatform: options.cachedSecChUaPlatform,
|
|
193
|
+
secChUaPlatformVersion: options.cachedSecChUaPlatformVersion,
|
|
194
|
+
browser: options.cachedBrowser || 'Google Chrome',
|
|
195
|
+
persona: 'desktop'
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const desktopData = randomUserAgent();
|
|
200
|
+
return {
|
|
201
|
+
...desktopData,
|
|
202
|
+
persona: 'desktop'
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function cachePersonaData(options, personaData) {
|
|
207
|
+
if (personaData.persona === 'android') {
|
|
208
|
+
options.cachedAndroidUA = personaData.userAgent;
|
|
209
|
+
options.cachedAndroidVersion = personaData.androidVersion;
|
|
210
|
+
options.cachedAndroidDevice = personaData.device;
|
|
211
|
+
options.cachedAndroidBuildId = personaData.buildId;
|
|
212
|
+
options.cachedAndroidResolution = personaData.resolution;
|
|
213
|
+
options.cachedAndroidFbav = personaData.fbav;
|
|
214
|
+
options.cachedAndroidFbbv = personaData.fbbv;
|
|
215
|
+
options.cachedAndroidLocale = personaData.locale;
|
|
216
|
+
options.cachedAndroidCarrier = personaData.carrier;
|
|
217
|
+
} else {
|
|
218
|
+
options.cachedUserAgent = personaData.userAgent;
|
|
219
|
+
options.cachedSecChUa = personaData.secChUa;
|
|
220
|
+
options.cachedSecChUaFullVersionList = personaData.secChUaFullVersionList;
|
|
221
|
+
options.cachedSecChUaPlatform = personaData.secChUaPlatform;
|
|
222
|
+
options.cachedSecChUaPlatformVersion = personaData.secChUaPlatformVersion;
|
|
223
|
+
options.cachedBrowser = personaData.browser;
|
|
224
|
+
}
|
|
225
|
+
return options;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
module.exports = {
|
|
229
|
+
defaultUserAgent,
|
|
230
|
+
windowsUserAgent: defaultUserAgent,
|
|
231
|
+
randomUserAgent,
|
|
232
|
+
randomBuildId,
|
|
233
|
+
randomResolution,
|
|
234
|
+
randomFbav,
|
|
235
|
+
randomOrcaUA,
|
|
236
|
+
generateUserAgentByPersona,
|
|
237
|
+
cachePersonaData,
|
|
238
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Input validation and sanitization utilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class InputValidator {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.maxMessageLength = 10000;
|
|
10
|
+
this.maxThreadNameLength = 255;
|
|
11
|
+
this.maxNicknameLength = 50;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Validate thread ID
|
|
16
|
+
* @param {string|number} threadID
|
|
17
|
+
* @returns {boolean}
|
|
18
|
+
*/
|
|
19
|
+
isValidThreadID(threadID) {
|
|
20
|
+
if (!threadID) return false;
|
|
21
|
+
const id = String(threadID).trim();
|
|
22
|
+
// Thread IDs are numeric, can be up to 20 digits
|
|
23
|
+
return /^\d{1,20}$/.test(id);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Validate user ID
|
|
28
|
+
* @param {string|number} userID
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
31
|
+
isValidUserID(userID) {
|
|
32
|
+
return this.isValidThreadID(userID); // Same format
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Validate message content
|
|
37
|
+
* @param {string|object} message
|
|
38
|
+
* @returns {boolean}
|
|
39
|
+
*/
|
|
40
|
+
isValidMessage(message) {
|
|
41
|
+
if (typeof message === 'string') {
|
|
42
|
+
return message.length > 0 && message.length <= this.maxMessageLength;
|
|
43
|
+
}
|
|
44
|
+
if (typeof message === 'object' && message !== null) {
|
|
45
|
+
return message.body || message.sticker || message.attachment || message.emoji;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Sanitize message content
|
|
52
|
+
* @param {string} message
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
sanitizeMessage(message) {
|
|
56
|
+
if (typeof message !== 'string') return message;
|
|
57
|
+
// Remove null bytes and control characters
|
|
58
|
+
return message.replace(/[\x00-\x1F\x7F]/g, '').trim();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Validate and sanitize thread name
|
|
63
|
+
* @param {string} name
|
|
64
|
+
* @returns {string|null}
|
|
65
|
+
*/
|
|
66
|
+
sanitizeThreadName(name) {
|
|
67
|
+
if (typeof name !== 'string') return null;
|
|
68
|
+
const sanitized = name.trim();
|
|
69
|
+
return sanitized.length > 0 && sanitized.length <= this.maxThreadNameLength ? sanitized : null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Validate and sanitize nickname
|
|
74
|
+
* @param {string} nickname
|
|
75
|
+
* @returns {string|null}
|
|
76
|
+
*/
|
|
77
|
+
sanitizeNickname(nickname) {
|
|
78
|
+
if (typeof nickname !== 'string') return null;
|
|
79
|
+
const sanitized = nickname.trim();
|
|
80
|
+
return sanitized.length > 0 && sanitized.length <= this.maxNicknameLength ? sanitized : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Validate array of IDs
|
|
85
|
+
* @param {Array} ids
|
|
86
|
+
* @param {function} validator
|
|
87
|
+
* @returns {boolean}
|
|
88
|
+
*/
|
|
89
|
+
validateIDArray(ids, validator = this.isValidThreadID.bind(this)) {
|
|
90
|
+
if (!Array.isArray(ids)) return false;
|
|
91
|
+
return ids.length > 0 && ids.length <= 100 && ids.every(validator);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Validate email
|
|
96
|
+
* @param {string} email
|
|
97
|
+
* @returns {boolean}
|
|
98
|
+
*/
|
|
99
|
+
isValidEmail(email) {
|
|
100
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
101
|
+
return emailRegex.test(email);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Validate URL
|
|
106
|
+
* @param {string} url
|
|
107
|
+
* @returns {boolean}
|
|
108
|
+
*/
|
|
109
|
+
isValidUrl(url) {
|
|
110
|
+
try {
|
|
111
|
+
new URL(url);
|
|
112
|
+
return true;
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Validate file path (basic check)
|
|
120
|
+
* @param {string} path
|
|
121
|
+
* @returns {boolean}
|
|
122
|
+
*/
|
|
123
|
+
isValidFilePath(path) {
|
|
124
|
+
if (typeof path !== 'string') return false;
|
|
125
|
+
// Basic check - no null bytes, reasonable length
|
|
126
|
+
return path.length > 0 && path.length <= 255 && !path.includes('\x00');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Validate emoji
|
|
131
|
+
* @param {string} emoji
|
|
132
|
+
* @returns {boolean}
|
|
133
|
+
*/
|
|
134
|
+
isValidEmoji(emoji) {
|
|
135
|
+
if (typeof emoji !== 'string') return false;
|
|
136
|
+
// Check if it's an emoji (basic check)
|
|
137
|
+
return /\p{Emoji}/u.test(emoji) || emoji.length === 1;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const globalValidator = new InputValidator();
|
|
142
|
+
|
|
143
|
+
module.exports = {
|
|
144
|
+
InputValidator,
|
|
145
|
+
globalValidator,
|
|
146
|
+
validateThreadID: (id) => globalValidator.isValidThreadID(id),
|
|
147
|
+
validateUserID: (id) => globalValidator.isValidUserID(id),
|
|
148
|
+
validateMessage: (msg) => globalValidator.isValidMessage(msg),
|
|
149
|
+
sanitizeMessage: (msg) => globalValidator.sanitizeMessage(msg),
|
|
150
|
+
sanitizeThreadName: (name) => globalValidator.sanitizeThreadName(name),
|
|
151
|
+
sanitizeNickname: (nick) => globalValidator.sanitizeNickname(nick),
|
|
152
|
+
validateIDArray: (ids, validator) => globalValidator.validateIDArray(ids, validator),
|
|
153
|
+
isValidEmail: (email) => globalValidator.isValidEmail(email),
|
|
154
|
+
isValidUrl: (url) => globalValidator.isValidUrl(url),
|
|
155
|
+
isValidFilePath: (path) => globalValidator.isValidFilePath(path),
|
|
156
|
+
isValidEmoji: (emoji) => globalValidator.isValidEmoji(emoji)
|
|
157
|
+
};
|
package/replit.nix
DELETED
package/src/addExternalModule.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const utils = require("../utils");
|
|
4
|
-
|
|
5
|
-
module.exports = function (defaultFuncs, api, ctx) {
|
|
6
|
-
return function addExternalModule(moduleObj) {
|
|
7
|
-
const moduleType = utils.getType(moduleObj);
|
|
8
|
-
|
|
9
|
-
if (moduleType !== "Object") {
|
|
10
|
-
throw new Error(`moduleObj must be an object, not ${moduleType}!`);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
Object.keys(moduleObj).forEach((apiName) => {
|
|
14
|
-
const functionType = utils.getType(moduleObj[apiName]);
|
|
15
|
-
|
|
16
|
-
if (functionType === "Function") {
|
|
17
|
-
api[apiName] = moduleObj[apiName](defaultFuncs, api, ctx);
|
|
18
|
-
} else {
|
|
19
|
-
throw new Error(
|
|
20
|
-
`Item "${apiName}" in moduleObj must be a function, not ${functionType}!`
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
};
|
package/src/addUserToGroup.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const utils = require("../utils");
|
|
4
|
-
|
|
5
|
-
module.exports = function (defaultFuncs, api, ctx) {
|
|
6
|
-
return function addUserToGroup(userID, threadID, callback) {
|
|
7
|
-
let resolveFunc = () => {};
|
|
8
|
-
let rejectFunc = () => {};
|
|
9
|
-
const returnPromise = new Promise((resolve, reject) => {
|
|
10
|
-
resolveFunc = resolve;
|
|
11
|
-
rejectFunc = reject;
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
const threadIDType = utils.getType(threadID);
|
|
15
|
-
|
|
16
|
-
if (!callback && (threadIDType === "Function" || threadIDType === "AsyncFunction")) {
|
|
17
|
-
throw new utils.CustomError({
|
|
18
|
-
error: "please pass a threadID as a second argument.",
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!callback) {
|
|
23
|
-
callback = function (err) {
|
|
24
|
-
if (err) return rejectFunc(err);
|
|
25
|
-
resolveFunc();
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (threadIDType !== "Number" && threadIDType !== "String") {
|
|
30
|
-
throw new utils.CustomError({
|
|
31
|
-
error: `ThreadID should be of type Number or String and not ${threadIDType}.`,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// userID অ্যারে না হলে অ্যারেতে কনভার্ট করা হচ্ছে
|
|
36
|
-
if (utils.getType(userID) !== "Array") {
|
|
37
|
-
userID = [userID];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const messageAndOTID = utils.generateOfflineThreadingID();
|
|
41
|
-
const form = {
|
|
42
|
-
client: "mercury",
|
|
43
|
-
action_type: "ma-type:log-message",
|
|
44
|
-
author: "fbid:" + ctx.userID,
|
|
45
|
-
thread_id: "",
|
|
46
|
-
timestamp: Date.now(),
|
|
47
|
-
timestamp_absolute: "Today",
|
|
48
|
-
timestamp_relative: utils.generateTimestampRelative(),
|
|
49
|
-
timestamp_time_passed: "0",
|
|
50
|
-
is_unread: false,
|
|
51
|
-
is_cleared: false,
|
|
52
|
-
is_forward: false,
|
|
53
|
-
is_filtered_content: false,
|
|
54
|
-
is_filtered_content_bh: false,
|
|
55
|
-
is_filtered_content_account: false,
|
|
56
|
-
is_spoof_warning: false,
|
|
57
|
-
source: "source:chat:web",
|
|
58
|
-
"source_tags[0]": "source:chat",
|
|
59
|
-
log_message_type: "log:subscribe",
|
|
60
|
-
status: "0",
|
|
61
|
-
offline_threading_id: messageAndOTID,
|
|
62
|
-
message_id: messageAndOTID,
|
|
63
|
-
threading_id: utils.generateThreadingID(ctx.clientID),
|
|
64
|
-
manual_retry_cnt: "0",
|
|
65
|
-
thread_fbid: threadID,
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// userID ভ্যালিডেশন এবং ফর্ম ডেটা বিল্ড
|
|
69
|
-
userID.forEach((id, index) => {
|
|
70
|
-
const idType = utils.getType(id);
|
|
71
|
-
if (idType !== "Number" && idType !== "String") {
|
|
72
|
-
throw new utils.CustomError({
|
|
73
|
-
error: `Elements of userID should be of type Number or String and not ${idType}.`,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
form[`log_message_data[added_participants][${index}]`] = "fbid:" + id;
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
defaultFuncs
|
|
80
|
-
.post("https://www.facebook.com/messaging/send/", ctx.jar, form)
|
|
81
|
-
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
82
|
-
.then(function (resData) {
|
|
83
|
-
if (!resData) {
|
|
84
|
-
throw new utils.CustomError({ error: "Add to group failed." });
|
|
85
|
-
}
|
|
86
|
-
if (resData.error) {
|
|
87
|
-
throw new utils.CustomError(resData);
|
|
88
|
-
}
|
|
89
|
-
return callback();
|
|
90
|
-
})
|
|
91
|
-
.catch(function (err) {
|
|
92
|
-
utils.error("addUserToGroup", err);
|
|
93
|
-
return callback(err);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
return returnPromise;
|
|
97
|
-
};
|
|
98
|
-
};
|
package/src/changeAdminStatus.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const utils = require("../utils");
|
|
4
|
-
|
|
5
|
-
module.exports = function (defaultFuncs, api, ctx) {
|
|
6
|
-
return function changeAdminStatus(threadID, adminIDs, adminStatus, callback) {
|
|
7
|
-
const threadIDType = utils.getType(threadID);
|
|
8
|
-
const adminIDsType = utils.getType(adminIDs);
|
|
9
|
-
const adminStatusType = utils.getType(adminStatus);
|
|
10
|
-
|
|
11
|
-
if (threadIDType !== "String") {
|
|
12
|
-
throw new utils.CustomError({
|
|
13
|
-
error: "changeAdminStatus: threadID must be a string",
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (adminIDsType === "String") {
|
|
18
|
-
adminIDs = [adminIDs];
|
|
19
|
-
} else if (utils.getType(adminIDs) !== "Array") { // রি-চেক করা হচ্ছে যদি স্ট্রিং না হয়
|
|
20
|
-
throw new utils.CustomError({
|
|
21
|
-
error: "changeAdminStatus: adminIDs must be an array or string",
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (adminStatusType !== "Boolean") {
|
|
26
|
-
throw new utils.CustomError({
|
|
27
|
-
error: "changeAdminStatus: adminStatus must be a boolean", // বাগ ফিক্স করা হয়েছে
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let resolveFunc = () => {};
|
|
32
|
-
let rejectFunc = () => {};
|
|
33
|
-
const returnPromise = new Promise((resolve, reject) => {
|
|
34
|
-
resolveFunc = resolve;
|
|
35
|
-
rejectFunc = reject;
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
if (!callback) {
|
|
39
|
-
callback = function (err) {
|
|
40
|
-
if (err) return rejectFunc(err);
|
|
41
|
-
resolveFunc();
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const callbackType = utils.getType(callback);
|
|
46
|
-
if (callbackType !== "Function" && callbackType !== "AsyncFunction") {
|
|
47
|
-
throw new utils.CustomError({
|
|
48
|
-
error: "changeAdminStatus: callback is not a function",
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const form = {
|
|
53
|
-
thread_fbid: threadID,
|
|
54
|
-
add: adminStatus,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// forEach ব্যবহার করে দ্রুত ফর্ম ডেটা রেডি করা হচ্ছে
|
|
58
|
-
adminIDs.forEach((u, i) => {
|
|
59
|
-
form[`admin_ids[${i}]`] = u;
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
defaultFuncs
|
|
63
|
-
.post(
|
|
64
|
-
"https://www.facebook.com/messaging/save_admins/?dpr=1",
|
|
65
|
-
ctx.jar,
|
|
66
|
-
form
|
|
67
|
-
)
|
|
68
|
-
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
69
|
-
.then(function (resData) {
|
|
70
|
-
if (resData.error) {
|
|
71
|
-
switch (resData.error) {
|
|
72
|
-
case 1976004:
|
|
73
|
-
throw new utils.CustomError({
|
|
74
|
-
error: "Cannot alter admin status: you are not an admin.",
|
|
75
|
-
rawResponse: resData,
|
|
76
|
-
});
|
|
77
|
-
case 1357031:
|
|
78
|
-
throw new utils.CustomError({
|
|
79
|
-
error: "Cannot alter admin status: this thread is not a group chat.",
|
|
80
|
-
rawResponse: resData,
|
|
81
|
-
});
|
|
82
|
-
default:
|
|
83
|
-
throw new utils.CustomError({
|
|
84
|
-
error: "Cannot alter admin status: unknown error.",
|
|
85
|
-
rawResponse: resData,
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return callback();
|
|
90
|
-
})
|
|
91
|
-
.catch(function (err) {
|
|
92
|
-
utils.error("changeAdminStatus", err);
|
|
93
|
-
return callback(err);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
return returnPromise;
|
|
97
|
-
};
|
|
98
|
-
};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const utils = require("../utils");
|
|
4
|
-
|
|
5
|
-
module.exports = function (defaultFuncs, api, ctx) {
|
|
6
|
-
return function changeArchivedStatus(threadOrThreads, archive, callback) {
|
|
7
|
-
let resolveFunc = () => {};
|
|
8
|
-
let rejectFunc = () => {};
|
|
9
|
-
const returnPromise = new Promise((resolve, reject) => {
|
|
10
|
-
resolveFunc = resolve;
|
|
11
|
-
rejectFunc = reject;
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
if (!callback) {
|
|
15
|
-
callback = function (err) {
|
|
16
|
-
if (err) return rejectFunc(err);
|
|
17
|
-
resolveFunc();
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const form = {};
|
|
22
|
-
|
|
23
|
-
// ইনপুট অ্যারে না হলে তা অ্যারেতে রূপান্তর করা হচ্ছে
|
|
24
|
-
const threads = utils.getType(threadOrThreads) === "Array" ? threadOrThreads : [threadOrThreads];
|
|
25
|
-
|
|
26
|
-
// দ্রুত লুপ চালিয়ে ফর্ম ডেটা রেডি করা হচ্ছে
|
|
27
|
-
threads.forEach((threadID) => {
|
|
28
|
-
form[`ids[${threadID}]`] = archive;
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
defaultFuncs
|
|
32
|
-
.post(
|
|
33
|
-
"https://www.facebook.com/ajax/mercury/change_archived_status.php",
|
|
34
|
-
ctx.jar,
|
|
35
|
-
form
|
|
36
|
-
)
|
|
37
|
-
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
38
|
-
.then(function (resData) {
|
|
39
|
-
if (resData.error) {
|
|
40
|
-
throw resData;
|
|
41
|
-
}
|
|
42
|
-
return callback();
|
|
43
|
-
})
|
|
44
|
-
.catch(function (err) {
|
|
45
|
-
utils.error("changeArchivedStatus", err);
|
|
46
|
-
return callback(err);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
return returnPromise;
|
|
50
|
-
};
|
|
51
|
-
};
|