@lazyneoaz/metachat 1.0.1 → 1.0.3
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyneoaz/metachat",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"types": "src/types/index.d.ts",
|
|
6
6
|
"description": "Advanced Facebook Chat API client for building Messenger bots — real-time messaging, thread management, MQTT, and session stability.",
|
|
@@ -54,7 +54,7 @@ async function buildAPI(html, jar, netData, globalOptions, fbLinkFunc, errorRetr
|
|
|
54
54
|
|
|
55
55
|
const dtsgResult = {
|
|
56
56
|
fb_dtsg: dtsg,
|
|
57
|
-
jazoest: `2${Array.from(dtsg).reduce((a, b) => a + b.charCodeAt(0),
|
|
57
|
+
jazoest: `2${Array.from(dtsg).reduce((a, b) => a + b.charCodeAt(0), 0)}`,
|
|
58
58
|
lsd: lsd
|
|
59
59
|
};
|
|
60
60
|
|
|
@@ -415,9 +415,11 @@ async function loginHelper(credentials, globalOptions, callback, setOptionsFunc,
|
|
|
415
415
|
// Use the lightweight presence endpoint instead of fetching the
|
|
416
416
|
// full homepage (~400 kB). Returns 200 JSON when authenticated,
|
|
417
417
|
// 302→login when the session is expired.
|
|
418
|
+
// Do NOT send fb_dtsg_ag= (empty) — real browsers always send a
|
|
419
|
+
// real token here, so an empty value is a bot fingerprint.
|
|
418
420
|
const resp = await utils.get(
|
|
419
|
-
'https://www.facebook.com/ajax/presence/reconnect.php
|
|
420
|
-
ctx.jar,
|
|
421
|
+
'https://www.facebook.com/ajax/presence/reconnect.php',
|
|
422
|
+
ctx.jar, { reason: '14', __a: '1' }, ctx.globalOptions, { noRef: true, _skipSessionInspect: true }
|
|
421
423
|
);
|
|
422
424
|
const html = resp.body || '';
|
|
423
425
|
|
|
@@ -83,8 +83,8 @@ class AntiSuspension {
|
|
|
83
83
|
this.lastActivity = new Map();
|
|
84
84
|
this.typing = new Map();
|
|
85
85
|
|
|
86
|
-
this.messageDelayMs =
|
|
87
|
-
this.threadDelayMs =
|
|
86
|
+
this.messageDelayMs = 300;
|
|
87
|
+
this.threadDelayMs = 400;
|
|
88
88
|
this.loginAttempts = 0;
|
|
89
89
|
this.maxLoginAttempts = 3;
|
|
90
90
|
this.loginCooldown = 300000;
|
|
@@ -279,9 +279,11 @@ class AntiSuspension {
|
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
async addSmartDelay() {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const
|
|
282
|
+
// Minimum realistic inter-request pause — short enough not to block
|
|
283
|
+
// high-throughput flows but long enough to avoid sub-100ms bot patterns.
|
|
284
|
+
const base = 500 + Math.random() * 700;
|
|
285
|
+
const jitter = (Math.random() - 0.5) * 150;
|
|
286
|
+
const total = Math.max(350, base + jitter);
|
|
285
287
|
await new Promise(resolve => setTimeout(resolve, total));
|
|
286
288
|
}
|
|
287
289
|
|
|
@@ -293,14 +295,14 @@ class AntiSuspension {
|
|
|
293
295
|
const threadCount = this.dailyStats.threadStats.get(String(threadID))?.count || 0;
|
|
294
296
|
const globalCount = this.dailyStats.messageCount;
|
|
295
297
|
|
|
296
|
-
let base =
|
|
297
|
-
if (globalCount > 800) base =
|
|
298
|
-
else if (globalCount > 400) base =
|
|
298
|
+
let base = 120;
|
|
299
|
+
if (globalCount > 800) base = 500;
|
|
300
|
+
else if (globalCount > 400) base = 250;
|
|
299
301
|
|
|
300
|
-
if (threadCount > 50) base +=
|
|
302
|
+
if (threadCount > 50) base += 180;
|
|
301
303
|
|
|
302
304
|
const jitter = Math.random() * base * 0.4;
|
|
303
|
-
const total = Math.max(
|
|
305
|
+
const total = Math.max(80, base + jitter);
|
|
304
306
|
await new Promise(resolve => setTimeout(resolve, total));
|
|
305
307
|
}
|
|
306
308
|
|
|
@@ -320,7 +322,7 @@ class AntiSuspension {
|
|
|
320
322
|
|
|
321
323
|
async enforceMessageRate() {
|
|
322
324
|
await new Promise(resolve =>
|
|
323
|
-
setTimeout(resolve, this.messageDelayMs + Math.random() *
|
|
325
|
+
setTimeout(resolve, this.messageDelayMs + Math.random() * 300)
|
|
324
326
|
);
|
|
325
327
|
}
|
|
326
328
|
|
|
@@ -457,7 +459,6 @@ class AntiSuspension {
|
|
|
457
459
|
}
|
|
458
460
|
|
|
459
461
|
await this.enforceThreadThrottling(threadID);
|
|
460
|
-
await this.addAdaptiveDelay(threadID);
|
|
461
462
|
this._incrementDailyStats(threadID);
|
|
462
463
|
}
|
|
463
464
|
|
package/src/utils/axios.js
CHANGED
|
@@ -111,18 +111,19 @@ async function inspectResponseForSessionIssues(adapted, ctx) {
|
|
|
111
111
|
|
|
112
112
|
if (!ctx.auto_login && typeof ctx.performAutoLogin === 'function') {
|
|
113
113
|
ctx.auto_login = true;
|
|
114
|
+
// Always reset the flag in a finally block so a synchronous throw
|
|
115
|
+
// or a rejected promise can never leave auto_login stuck at true,
|
|
116
|
+
// which would permanently prevent future re-login attempts.
|
|
114
117
|
try {
|
|
115
118
|
const ok = await ctx.performAutoLogin();
|
|
116
|
-
ctx.auto_login = false;
|
|
117
119
|
if (!ok) {
|
|
118
120
|
const err = new Error('Not logged in. Auto re-login failed.');
|
|
119
121
|
err.error = 'Not logged in.';
|
|
120
122
|
err.res = body;
|
|
121
123
|
throw err;
|
|
122
124
|
}
|
|
123
|
-
}
|
|
125
|
+
} finally {
|
|
124
126
|
ctx.auto_login = false;
|
|
125
|
-
throw autoErr;
|
|
126
127
|
}
|
|
127
128
|
} else {
|
|
128
129
|
const err = new Error('Not logged in. Session has expired.');
|
|
@@ -95,6 +95,11 @@ class TokenRefreshManager {
|
|
|
95
95
|
probeCtx
|
|
96
96
|
);
|
|
97
97
|
|
|
98
|
+
// Save any rotated cookies Facebook returns (fr, xs, etc.) so the
|
|
99
|
+
// jar stays fresh. Dropping rotated cookies causes Facebook to
|
|
100
|
+
// treat the session as stale and forces a logout.
|
|
101
|
+
try { utils.saveCookies(ctx.jar)(resp); } catch (_) {}
|
|
102
|
+
|
|
98
103
|
const body = resp.body;
|
|
99
104
|
if (!body) return false;
|
|
100
105
|
|
|
@@ -188,6 +193,9 @@ class TokenRefreshManager {
|
|
|
188
193
|
for (let i = 0; i < ctx.fb_dtsg.length; i++) {
|
|
189
194
|
ctx.ttstamp += ctx.fb_dtsg.charCodeAt(i);
|
|
190
195
|
}
|
|
196
|
+
// Recalculate jazoest whenever fb_dtsg changes — it must stay in sync.
|
|
197
|
+
// jazoest = "2" + sum-of-char-codes (numeric sum, not concatenation).
|
|
198
|
+
ctx.jazoest = `2${Array.from(ctx.fb_dtsg).reduce((a, b) => a + b.charCodeAt(0), 0)}`;
|
|
191
199
|
} else {
|
|
192
200
|
throw new Error("Failed to extract fb_dtsg token");
|
|
193
201
|
}
|