@lazyneoaz/metachat 4.0.6 → 4.0.8
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/dist/index.cjs +608 -78
- package/dist/index.d.mts +298 -1
- package/dist/index.d.ts +298 -1
- package/dist/index.mjs +601 -79
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -25142,13 +25142,15 @@ function getHeaders(url2, options, ctx, customHeader) {
|
|
|
25142
25142
|
headers["priority"] = "u=0, i";
|
|
25143
25143
|
}
|
|
25144
25144
|
if (isXhr) {
|
|
25145
|
-
|
|
25146
|
-
|
|
25147
|
-
|
|
25145
|
+
if (!isGraphQl) {
|
|
25146
|
+
headers["X-Requested-With"] = "XMLHttpRequest";
|
|
25147
|
+
headers["Pragma"] = "no-cache";
|
|
25148
|
+
headers["Cache-Control"] = "no-cache";
|
|
25149
|
+
}
|
|
25148
25150
|
headers["priority"] = "u=1, i";
|
|
25149
25151
|
}
|
|
25150
25152
|
if (isGraphQl) {
|
|
25151
|
-
headers["x-asbd-id"] =
|
|
25153
|
+
headers["x-asbd-id"] = String(ctx?.asbdId || DEFAULT_ASBD_ID);
|
|
25152
25154
|
const lsd = ctx?.lsd || ctx?.fb_lsd;
|
|
25153
25155
|
if (lsd) headers["x-fb-lsd"] = sanitizeHeaderValue2(lsd);
|
|
25154
25156
|
const friendlyName = customHeader?.["x-fb-friendly-name"] || customHeader?.["X-Fb-Friendly-Name"];
|
|
@@ -25219,10 +25221,11 @@ function getFingerprintParams(options) {
|
|
|
25219
25221
|
dpr: String(profile.devicePixelRatio)
|
|
25220
25222
|
};
|
|
25221
25223
|
}
|
|
25222
|
-
var meta;
|
|
25224
|
+
var DEFAULT_ASBD_ID, meta;
|
|
25223
25225
|
var init_headers = __esm({
|
|
25224
25226
|
"src/utils/headers.ts"() {
|
|
25225
25227
|
init_user_agents();
|
|
25228
|
+
DEFAULT_ASBD_ID = "359341";
|
|
25226
25229
|
meta = (prop2) => new RegExp(`<meta property="${prop2}" content="([^"]*)"`);
|
|
25227
25230
|
}
|
|
25228
25231
|
});
|
|
@@ -75560,9 +75563,13 @@ __export(utils_exports2, {
|
|
|
75560
75563
|
NUM_TO_MONTH: () => NUM_TO_MONTH,
|
|
75561
75564
|
NetworkError: () => NetworkError,
|
|
75562
75565
|
NotFoundError: () => NotFoundError,
|
|
75566
|
+
PING_GRACE_MS: () => PING_GRACE_MS,
|
|
75563
75567
|
PermissionError: () => PermissionError,
|
|
75564
75568
|
RateLimitError: () => RateLimitError,
|
|
75569
|
+
RealtimeHealth: () => RealtimeHealth,
|
|
75570
|
+
RecoverySupervisor: () => RecoverySupervisor,
|
|
75565
75571
|
SESSION_COOKIE_NAMES: () => SESSION_COOKIE_NAMES,
|
|
75572
|
+
SILENT_WINDOW_MS: () => SILENT_WINDOW_MS,
|
|
75566
75573
|
TimeoutError: () => TimeoutError,
|
|
75567
75574
|
ValidationError: () => ValidationError,
|
|
75568
75575
|
WINDOW_MS: () => WINDOW_MS,
|
|
@@ -75587,6 +75594,7 @@ __export(utils_exports2, {
|
|
|
75587
75594
|
delay: () => delay2,
|
|
75588
75595
|
ensureCometTokens: () => ensureCometTokens,
|
|
75589
75596
|
error: () => error,
|
|
75597
|
+
extractAsbdId: () => extractAsbdId,
|
|
75590
75598
|
extractAttachmentIds: () => extractAttachmentIds,
|
|
75591
75599
|
extractCookies: () => extractCookies,
|
|
75592
75600
|
extractCookiesFromBody: () => extractCookiesFromBody,
|
|
@@ -75637,6 +75645,7 @@ __export(utils_exports2, {
|
|
|
75637
75645
|
invalidateCometTokens: () => invalidateCometTokens,
|
|
75638
75646
|
isAuthFailure: () => isAuthFailure,
|
|
75639
75647
|
isBreakerOpen: () => isBreakerOpen,
|
|
75648
|
+
isLoggedOutDocument: () => isLoggedOutDocument,
|
|
75640
75649
|
isReadableStream: () => isReadableStream2,
|
|
75641
75650
|
isStaleTokenError: () => isStaleTokenError,
|
|
75642
75651
|
json: () => json2,
|
|
@@ -75674,6 +75683,8 @@ __export(utils_exports2, {
|
|
|
75674
75683
|
setProxy: () => setProxy2,
|
|
75675
75684
|
sleep: () => sleep,
|
|
75676
75685
|
startLiveness: () => startLiveness,
|
|
75686
|
+
startRealtimeSupervisor: () => startRealtimeSupervisor,
|
|
75687
|
+
startRecovery: () => startRecovery,
|
|
75677
75688
|
success: () => success,
|
|
75678
75689
|
tripBreaker: () => tripBreaker,
|
|
75679
75690
|
uploadGroupImage: () => uploadGroupImage,
|
|
@@ -91030,6 +91041,9 @@ function extractLsd(html3) {
|
|
|
91030
91041
|
function extractDtsg(html3) {
|
|
91031
91042
|
return getFrom3(html3, '["DTSGInitialData",[],{"token":"', '"}') || getFrom3(html3, 'name="fb_dtsg" value="', '"') || (html3.match(/"DTSGInitialData",\[\],\{"token":"([^"]+)"/) || [])[1] || "";
|
|
91032
91043
|
}
|
|
91044
|
+
function extractAsbdId(html3) {
|
|
91045
|
+
return (html3.match(/"asbd_id":(\d+)/) || [])[1] || (html3.match(/x-asbd-id["']?\s*[:=]\s*["']?(\d+)/i) || [])[1] || (html3.match(/"ASBD_ID":(\d+)/) || [])[1] || "";
|
|
91046
|
+
}
|
|
91033
91047
|
function extractSpin(html3) {
|
|
91034
91048
|
const out = {};
|
|
91035
91049
|
const spinB = (html3.match(/"__spin_b":"([^"]+)"/) || [])[1];
|
|
@@ -91096,6 +91110,8 @@ async function ensureCometTokens(ctx, defaultFuncs, force = false) {
|
|
|
91096
91110
|
const spin = extractSpin(html3);
|
|
91097
91111
|
if (Object.keys(spin).length) ctx.__spin = { ...ctx.__spin || {}, ...spin };
|
|
91098
91112
|
if (spin.__rev) ctx.revision = spin.__rev;
|
|
91113
|
+
const asbd = extractAsbdId(html3);
|
|
91114
|
+
if (asbd) ctx.asbdId = asbd;
|
|
91099
91115
|
ctx.lsd = lsd;
|
|
91100
91116
|
ctx.fb_dtsg = dtsg;
|
|
91101
91117
|
ctx.jazoest = recomputeJazoest(dtsg);
|
|
@@ -91366,6 +91382,13 @@ function isAuthFailure(value) {
|
|
|
91366
91382
|
}
|
|
91367
91383
|
return false;
|
|
91368
91384
|
}
|
|
91385
|
+
function isLoggedOutDocument(html3) {
|
|
91386
|
+
if (typeof html3 !== "string" || html3.length < 200) return false;
|
|
91387
|
+
if (!/<html/i.test(html3)) return false;
|
|
91388
|
+
const hasAuthedTokens = /DTSGInitialData|"LSD",\[\]/.test(html3);
|
|
91389
|
+
const looksLikeLogin = /name="(?:email|pass)"|id="email"|"login_form"|LoginForm|login_form/i.test(html3) || /Continue as |Use another profile|Create new account/i.test(html3) || /You must log in to continue|Please log in|log in to continue/i.test(html3);
|
|
91390
|
+
return looksLikeLogin && !hasAuthedTokens;
|
|
91391
|
+
}
|
|
91369
91392
|
async function withSessionRetry(ctx, defaultFuncs, operation, options = {}) {
|
|
91370
91393
|
const attempts = Math.max(1, options.attempts ?? 2);
|
|
91371
91394
|
let lastError;
|
|
@@ -91472,6 +91495,8 @@ async function warmUpSession(ctx, getter, options = {}) {
|
|
|
91472
91495
|
const spin = extractSpin(html3);
|
|
91473
91496
|
if (Object.keys(spin).length) ctx.__spin = { ...ctx.__spin || {}, ...spin };
|
|
91474
91497
|
if (spin.__rev) ctx.revision = spin.__rev;
|
|
91498
|
+
const asbd = extractAsbdId(html3);
|
|
91499
|
+
if (asbd) ctx.asbdId = asbd;
|
|
91475
91500
|
tokensSeeded = true;
|
|
91476
91501
|
}
|
|
91477
91502
|
} else if (url2.includes("/messages")) {
|
|
@@ -91570,6 +91595,339 @@ async function awaitProactiveSlot(ctx, maxWaitMs = 15 * 60 * 1e3) {
|
|
|
91570
91595
|
return false;
|
|
91571
91596
|
}
|
|
91572
91597
|
|
|
91598
|
+
// src/utils/recovery.ts
|
|
91599
|
+
init_pacing();
|
|
91600
|
+
init_safety();
|
|
91601
|
+
var DEFAULTS = {
|
|
91602
|
+
intervalMs: 10 * 60 * 1e3,
|
|
91603
|
+
failureThreshold: 3,
|
|
91604
|
+
maxRecoveries: 5
|
|
91605
|
+
};
|
|
91606
|
+
function randJitter(base, spread3 = 0.3) {
|
|
91607
|
+
return Math.floor(base * (1 - spread3 / 2 + Math.random() * spread3));
|
|
91608
|
+
}
|
|
91609
|
+
var RecoverySupervisor = class {
|
|
91610
|
+
constructor(runtime, options = {}) {
|
|
91611
|
+
this.timer = null;
|
|
91612
|
+
this.stopped = true;
|
|
91613
|
+
this.running = false;
|
|
91614
|
+
this.runtime = runtime;
|
|
91615
|
+
this.opts = {
|
|
91616
|
+
intervalMs: options.intervalMs ?? DEFAULTS.intervalMs,
|
|
91617
|
+
failureThreshold: options.failureThreshold ?? DEFAULTS.failureThreshold,
|
|
91618
|
+
maxRecoveries: options.maxRecoveries ?? DEFAULTS.maxRecoveries,
|
|
91619
|
+
noRelogin: options.noRelogin ?? false
|
|
91620
|
+
};
|
|
91621
|
+
this.backoffMs = this.opts.intervalMs;
|
|
91622
|
+
this.state = {
|
|
91623
|
+
phase: "healthy",
|
|
91624
|
+
checks: 0,
|
|
91625
|
+
consecutiveFailures: 0,
|
|
91626
|
+
healCount: 0,
|
|
91627
|
+
attempts: 0,
|
|
91628
|
+
reloginCount: 0,
|
|
91629
|
+
givenUp: 0,
|
|
91630
|
+
lastHealthyAt: Date.now(),
|
|
91631
|
+
nextCheckMs: 0,
|
|
91632
|
+
canRelogin: typeof runtime.relogin === "function" && !this.opts.noRelogin && (runtime.canRelogin !== void 0 ? runtime.canRelogin : true)
|
|
91633
|
+
};
|
|
91634
|
+
}
|
|
91635
|
+
/** A point-in-time copy of the supervisor state. */
|
|
91636
|
+
snapshot() {
|
|
91637
|
+
return { ...this.state, nextCheckMs: Math.max(0, this.nextCheckAt() - Date.now()) };
|
|
91638
|
+
}
|
|
91639
|
+
isRunning() {
|
|
91640
|
+
return !this.stopped;
|
|
91641
|
+
}
|
|
91642
|
+
/** Start the supervisor. Idempotent. */
|
|
91643
|
+
start() {
|
|
91644
|
+
if (!this.stopped) return;
|
|
91645
|
+
this.stopped = false;
|
|
91646
|
+
if (this.state.phase === "stopped") this.state.phase = "healthy";
|
|
91647
|
+
this.startTimer(false);
|
|
91648
|
+
this.emit("check", "recovery supervisor started");
|
|
91649
|
+
}
|
|
91650
|
+
/** Stop the supervisor and clear any pending timer. */
|
|
91651
|
+
stop() {
|
|
91652
|
+
this.stopped = true;
|
|
91653
|
+
if (this.timer) {
|
|
91654
|
+
clearTimeout(this.timer);
|
|
91655
|
+
this.timer = null;
|
|
91656
|
+
}
|
|
91657
|
+
this.state.phase = "stopped";
|
|
91658
|
+
this.emit("stopped", "recovery supervisor stopped");
|
|
91659
|
+
}
|
|
91660
|
+
/**
|
|
91661
|
+
* Run one health check immediately (used by tests and by `checkNow()`).
|
|
91662
|
+
* Returns the resulting state. Never throws.
|
|
91663
|
+
*/
|
|
91664
|
+
async checkNow() {
|
|
91665
|
+
if (this.running) return this.snapshot();
|
|
91666
|
+
this.running = true;
|
|
91667
|
+
try {
|
|
91668
|
+
await this.runOnce();
|
|
91669
|
+
} catch {
|
|
91670
|
+
} finally {
|
|
91671
|
+
this.running = false;
|
|
91672
|
+
}
|
|
91673
|
+
return this.snapshot();
|
|
91674
|
+
}
|
|
91675
|
+
nextCheckAt() {
|
|
91676
|
+
return this.state.nextCheckMs && this.timer ? Date.now() + this.state.nextCheckMs : 0;
|
|
91677
|
+
}
|
|
91678
|
+
startTimer(delayOverride) {
|
|
91679
|
+
if (this.stopped) return;
|
|
91680
|
+
if (this.timer) {
|
|
91681
|
+
clearTimeout(this.timer);
|
|
91682
|
+
this.timer = null;
|
|
91683
|
+
}
|
|
91684
|
+
const delay3 = delayOverride === false ? this.backoffMs : delayOverride ?? this.backoffMs;
|
|
91685
|
+
const jittered = randJitter(delay3);
|
|
91686
|
+
this.state.nextCheckMs = jittered;
|
|
91687
|
+
this.timer = setTimeout(() => {
|
|
91688
|
+
this.timer = null;
|
|
91689
|
+
this.state.nextCheckMs = 0;
|
|
91690
|
+
void this.checkNow().finally(() => {
|
|
91691
|
+
if (!this.stopped) this.startTimer();
|
|
91692
|
+
});
|
|
91693
|
+
}, jittered);
|
|
91694
|
+
if (this.timer && typeof this.timer.unref === "function") this.timer.unref();
|
|
91695
|
+
}
|
|
91696
|
+
async runOnce() {
|
|
91697
|
+
this.state.checks += 1;
|
|
91698
|
+
this.emit("check", `health check #${this.state.checks}`);
|
|
91699
|
+
let healthy = this.runtime.isAuthenticated();
|
|
91700
|
+
if (healthy && this.runtime.probeLiveness) {
|
|
91701
|
+
try {
|
|
91702
|
+
healthy = await this.runtime.probeLiveness();
|
|
91703
|
+
} catch {
|
|
91704
|
+
healthy = true;
|
|
91705
|
+
}
|
|
91706
|
+
}
|
|
91707
|
+
if (healthy) {
|
|
91708
|
+
this.markHealthy("session authenticated");
|
|
91709
|
+
return;
|
|
91710
|
+
}
|
|
91711
|
+
this.state.consecutiveFailures += 1;
|
|
91712
|
+
this.state.phase = "refreshing";
|
|
91713
|
+
this.emit("unhealthy", `unauthenticated (${this.state.consecutiveFailures}/${this.opts.failureThreshold})`);
|
|
91714
|
+
if (this.state.consecutiveFailures < this.opts.failureThreshold) {
|
|
91715
|
+
return;
|
|
91716
|
+
}
|
|
91717
|
+
if (isBreakerOpen(this.runtime.ctx)) {
|
|
91718
|
+
this.state.phase = "cooling";
|
|
91719
|
+
this.emit("cooling", "safety breaker open; delaying recovery");
|
|
91720
|
+
return;
|
|
91721
|
+
}
|
|
91722
|
+
if (this.state.attempts >= this.opts.maxRecoveries) {
|
|
91723
|
+
this.state.phase = "cooling";
|
|
91724
|
+
this.state.givenUp += 1;
|
|
91725
|
+
this.emit("gave-up", "recovery budget exhausted");
|
|
91726
|
+
return;
|
|
91727
|
+
}
|
|
91728
|
+
this.state.attempts += 1;
|
|
91729
|
+
let healed = false;
|
|
91730
|
+
try {
|
|
91731
|
+
healed = await this.runtime.refresh();
|
|
91732
|
+
} catch {
|
|
91733
|
+
healed = false;
|
|
91734
|
+
}
|
|
91735
|
+
if (healed && this.runtime.isAuthenticated()) {
|
|
91736
|
+
this.state.healCount += 1;
|
|
91737
|
+
this.markHealthy("cookie refresh restored the session");
|
|
91738
|
+
this.afterRecovery();
|
|
91739
|
+
return;
|
|
91740
|
+
}
|
|
91741
|
+
if (!this.state.canRelogin || !this.runtime.relogin) {
|
|
91742
|
+
this.state.phase = "cooling";
|
|
91743
|
+
this.state.givenUp += 1;
|
|
91744
|
+
this.emit(
|
|
91745
|
+
"gave-up",
|
|
91746
|
+
"session unauthenticated and no credentials available for re-login; provide email+password or a fresh appState"
|
|
91747
|
+
);
|
|
91748
|
+
return;
|
|
91749
|
+
}
|
|
91750
|
+
this.state.phase = "relogin";
|
|
91751
|
+
let fresh = null;
|
|
91752
|
+
try {
|
|
91753
|
+
fresh = await this.runtime.relogin();
|
|
91754
|
+
} catch {
|
|
91755
|
+
fresh = null;
|
|
91756
|
+
}
|
|
91757
|
+
if (Array.isArray(fresh) && fresh.length > 0) {
|
|
91758
|
+
this.state.reloginCount += 1;
|
|
91759
|
+
try {
|
|
91760
|
+
this.runtime.persistAppState?.(fresh);
|
|
91761
|
+
} catch {
|
|
91762
|
+
}
|
|
91763
|
+
this.markHealthy("credential re-login succeeded");
|
|
91764
|
+
this.afterRecovery();
|
|
91765
|
+
return;
|
|
91766
|
+
}
|
|
91767
|
+
this.state.phase = "cooling";
|
|
91768
|
+
this.state.givenUp += 1;
|
|
91769
|
+
this.emit("gave-up", "credential re-login did not return a fresh session");
|
|
91770
|
+
}
|
|
91771
|
+
markHealthy(detail) {
|
|
91772
|
+
this.state.phase = "healthy";
|
|
91773
|
+
this.state.consecutiveFailures = 0;
|
|
91774
|
+
this.state.lastHealthyAt = Date.now();
|
|
91775
|
+
this.state.lastDetail = detail;
|
|
91776
|
+
this.backoffMs = this.opts.intervalMs;
|
|
91777
|
+
this.emit("healed", detail);
|
|
91778
|
+
}
|
|
91779
|
+
afterRecovery() {
|
|
91780
|
+
try {
|
|
91781
|
+
this.runtime.restartMqtt?.();
|
|
91782
|
+
} catch {
|
|
91783
|
+
}
|
|
91784
|
+
}
|
|
91785
|
+
emit(type, detail) {
|
|
91786
|
+
if (!this.runtime.onEvent) return;
|
|
91787
|
+
try {
|
|
91788
|
+
this.runtime.onEvent({ type, detail, state: this.snapshot() });
|
|
91789
|
+
} catch {
|
|
91790
|
+
}
|
|
91791
|
+
}
|
|
91792
|
+
};
|
|
91793
|
+
function startRecovery(ctx, runtime, options = {}) {
|
|
91794
|
+
if (ctx.__recovery && typeof ctx.__recovery.stop === "function") {
|
|
91795
|
+
try {
|
|
91796
|
+
ctx.__recovery.stop();
|
|
91797
|
+
} catch {
|
|
91798
|
+
}
|
|
91799
|
+
}
|
|
91800
|
+
const supervisor = new RecoverySupervisor(runtime, options);
|
|
91801
|
+
ctx.__recovery = supervisor;
|
|
91802
|
+
supervisor.start();
|
|
91803
|
+
return supervisor;
|
|
91804
|
+
}
|
|
91805
|
+
|
|
91806
|
+
// src/utils/realtime-health.ts
|
|
91807
|
+
init_pacing();
|
|
91808
|
+
var SILENT_WINDOW_MS = 6 * 60 * 1e3;
|
|
91809
|
+
var PING_GRACE_MS = 45 * 1e3;
|
|
91810
|
+
var RealtimeHealth = class {
|
|
91811
|
+
constructor(now = () => Date.now()) {
|
|
91812
|
+
this.now = now;
|
|
91813
|
+
this.frames = 0;
|
|
91814
|
+
this.lastFrameAt = 0;
|
|
91815
|
+
this.connectedAt = 0;
|
|
91816
|
+
this.probes = 0;
|
|
91817
|
+
this.forcedReconnects = 0;
|
|
91818
|
+
this.lastPingAt = 0;
|
|
91819
|
+
this.startedAt = Date.now();
|
|
91820
|
+
this.startedAt = this.now();
|
|
91821
|
+
}
|
|
91822
|
+
/** Record any inbound frame (message, pong, anything from the broker). */
|
|
91823
|
+
noteFrame() {
|
|
91824
|
+
this.frames += 1;
|
|
91825
|
+
this.lastFrameAt = this.now();
|
|
91826
|
+
}
|
|
91827
|
+
/** Record a successful connect. */
|
|
91828
|
+
noteConnected() {
|
|
91829
|
+
this.connectedAt = this.now();
|
|
91830
|
+
this.lastFrameAt = this.now();
|
|
91831
|
+
}
|
|
91832
|
+
/** Record that the transport reports itself disconnected. */
|
|
91833
|
+
noteDisconnected() {
|
|
91834
|
+
this.lastFrameAt = 0;
|
|
91835
|
+
}
|
|
91836
|
+
/** Record an active ping being sent. */
|
|
91837
|
+
notePing() {
|
|
91838
|
+
this.lastPingAt = this.now();
|
|
91839
|
+
}
|
|
91840
|
+
sinceLastFrame() {
|
|
91841
|
+
const base = this.lastFrameAt || this.connectedAt || this.startedAt;
|
|
91842
|
+
return this.now() - base;
|
|
91843
|
+
}
|
|
91844
|
+
/**
|
|
91845
|
+
* Decide what to do about the current socket.
|
|
91846
|
+
*
|
|
91847
|
+
* - `disconnected` — the transport already knows it is down; reconnect.
|
|
91848
|
+
* - `dead` — connected on paper, silent past the window, and a ping raised no
|
|
91849
|
+
* traffic within the grace period; reconnect.
|
|
91850
|
+
* - `suspect` — silent past the window but a ping was only just sent; wait.
|
|
91851
|
+
* - `quiet` — silent but inside the window; normal.
|
|
91852
|
+
* - `healthy` — recent traffic.
|
|
91853
|
+
*/
|
|
91854
|
+
verdict(connected) {
|
|
91855
|
+
if (!connected) return "disconnected";
|
|
91856
|
+
const silent = this.sinceLastFrame();
|
|
91857
|
+
if (silent < SILENT_WINDOW_MS / 2) return "healthy";
|
|
91858
|
+
if (silent < SILENT_WINDOW_MS) return "quiet";
|
|
91859
|
+
if (this.lastPingAt && this.now() - this.lastPingAt < PING_GRACE_MS) return "suspect";
|
|
91860
|
+
return "dead";
|
|
91861
|
+
}
|
|
91862
|
+
/** A snapshot for diagnostics. */
|
|
91863
|
+
state(connected) {
|
|
91864
|
+
return {
|
|
91865
|
+
connected,
|
|
91866
|
+
sinceLastFrameMs: this.sinceLastFrame(),
|
|
91867
|
+
frames: this.frames,
|
|
91868
|
+
probes: this.probes,
|
|
91869
|
+
forcedReconnects: this.forcedReconnects,
|
|
91870
|
+
verdict: this.verdict(connected)
|
|
91871
|
+
};
|
|
91872
|
+
}
|
|
91873
|
+
noteProbe() {
|
|
91874
|
+
this.probes += 1;
|
|
91875
|
+
}
|
|
91876
|
+
noteForcedReconnect() {
|
|
91877
|
+
this.forcedReconnects += 1;
|
|
91878
|
+
}
|
|
91879
|
+
};
|
|
91880
|
+
function startRealtimeSupervisor(options) {
|
|
91881
|
+
const health = new RealtimeHealth();
|
|
91882
|
+
const interval = options.intervalMs ?? 3 * 60 * 1e3;
|
|
91883
|
+
let stopped = false;
|
|
91884
|
+
let timer = null;
|
|
91885
|
+
const evaluate = () => {
|
|
91886
|
+
const connected = options.isConnected();
|
|
91887
|
+
const verdict = health.verdict(connected);
|
|
91888
|
+
health.noteProbe();
|
|
91889
|
+
if (verdict === "dead") {
|
|
91890
|
+
const pingSent = options.ping ? options.ping() : false;
|
|
91891
|
+
if (pingSent) {
|
|
91892
|
+
health.notePing();
|
|
91893
|
+
} else {
|
|
91894
|
+
health.noteForcedReconnect();
|
|
91895
|
+
options.reconnect("realtime socket silent and unpinnable");
|
|
91896
|
+
}
|
|
91897
|
+
}
|
|
91898
|
+
const state = health.state(connected);
|
|
91899
|
+
try {
|
|
91900
|
+
options.onVerdict?.(state);
|
|
91901
|
+
} catch {
|
|
91902
|
+
}
|
|
91903
|
+
return state;
|
|
91904
|
+
};
|
|
91905
|
+
const schedule = () => {
|
|
91906
|
+
if (stopped) return;
|
|
91907
|
+
timer = setTimeout(
|
|
91908
|
+
() => {
|
|
91909
|
+
timer = null;
|
|
91910
|
+
evaluate();
|
|
91911
|
+
schedule();
|
|
91912
|
+
},
|
|
91913
|
+
Math.max(1e3, humanDelay(interval, interval * 0.3))
|
|
91914
|
+
);
|
|
91915
|
+
if (timer && typeof timer.unref === "function") timer.unref();
|
|
91916
|
+
};
|
|
91917
|
+
schedule();
|
|
91918
|
+
return {
|
|
91919
|
+
health,
|
|
91920
|
+
checkNow: evaluate,
|
|
91921
|
+
stop: () => {
|
|
91922
|
+
stopped = true;
|
|
91923
|
+
if (timer) {
|
|
91924
|
+
clearTimeout(timer);
|
|
91925
|
+
timer = null;
|
|
91926
|
+
}
|
|
91927
|
+
}
|
|
91928
|
+
};
|
|
91929
|
+
}
|
|
91930
|
+
|
|
91573
91931
|
// src/utils/index.ts
|
|
91574
91932
|
async function json2(url2, jar2, qs2, options, ctx, customHeader) {
|
|
91575
91933
|
try {
|
|
@@ -91787,6 +92145,7 @@ async function buildAPI(html3, jar2, netData, globalOptions, fbLinkFunc, errorRe
|
|
|
91787
92145
|
const lsd = lsdConfig && lsdConfig.token || extractLsd(html3) || void 0;
|
|
91788
92146
|
const spin = extractSpin(html3);
|
|
91789
92147
|
const revision = spin.__rev || getFrom(html3, 'revision":', ",").trim();
|
|
92148
|
+
const asbdId = extractAsbdId(html3) || void 0;
|
|
91790
92149
|
const clientIDData = findConfig("MqttWebDeviceID");
|
|
91791
92150
|
const clientID = clientIDData ? clientIDData.clientID : void 0;
|
|
91792
92151
|
const mqttConfigData = findConfig("MqttWebConfig");
|
|
@@ -91828,7 +92187,8 @@ async function buildAPI(html3, jar2, netData, globalOptions, fbLinkFunc, errorRe
|
|
|
91828
92187
|
...dtsgResult,
|
|
91829
92188
|
...lsd ? { lsd } : {},
|
|
91830
92189
|
...Object.keys(spin).length ? { __spin: spin } : {},
|
|
91831
|
-
...revision ? { revision } : {}
|
|
92190
|
+
...revision ? { revision } : {},
|
|
92191
|
+
...asbdId ? { asbdId } : {}
|
|
91832
92192
|
};
|
|
91833
92193
|
if (lsd && dtsg) {
|
|
91834
92194
|
ctx.__cometTokens = { lsd, fb_dtsg: dtsg, fetchedAt: Date.now(), failures: 0 };
|
|
@@ -91837,8 +92197,95 @@ async function buildAPI(html3, jar2, netData, globalOptions, fbLinkFunc, errorRe
|
|
|
91837
92197
|
return [ctx, defaultFuncs, {}];
|
|
91838
92198
|
}
|
|
91839
92199
|
|
|
91840
|
-
// src/core/models/
|
|
92200
|
+
// src/core/models/acquireCookies.ts
|
|
91841
92201
|
init_axios2();
|
|
92202
|
+
function cookieStringFromObject(cookie, index3) {
|
|
92203
|
+
const name = cookie && (cookie.name || cookie.key);
|
|
92204
|
+
if (!name || cookie.value === void 0 || cookie.value === null) {
|
|
92205
|
+
throw new Error(`Invalid appState cookie at index ${index3}.`);
|
|
92206
|
+
}
|
|
92207
|
+
return formatAppStateCookie(cookie);
|
|
92208
|
+
}
|
|
92209
|
+
function writeCookie(jar2, cookieString) {
|
|
92210
|
+
const normalized = cookieString.replace(/;\s*domain=facebook\.com/i, "; domain=.facebook.com").replace(/;\s*domain=messenger\.com/i, "; domain=.messenger.com");
|
|
92211
|
+
const str = /(^|;)\s*domain=/i.test(normalized) ? normalized : `${normalized}; domain=.facebook.com; path=/; Secure; SameSite=None`;
|
|
92212
|
+
try {
|
|
92213
|
+
jar2.setCookieSync(str, "https://facebook.com");
|
|
92214
|
+
return true;
|
|
92215
|
+
} catch {
|
|
92216
|
+
try {
|
|
92217
|
+
jar2.setCookieSync(
|
|
92218
|
+
`${normalized}; domain=.facebook.com; path=/; Secure; SameSite=None`,
|
|
92219
|
+
"https://www.facebook.com"
|
|
92220
|
+
);
|
|
92221
|
+
return true;
|
|
92222
|
+
} catch {
|
|
92223
|
+
return false;
|
|
92224
|
+
}
|
|
92225
|
+
}
|
|
92226
|
+
}
|
|
92227
|
+
async function acquireCookies(jar2, credentials, globalOptions) {
|
|
92228
|
+
const appState = credentials.appState;
|
|
92229
|
+
if (Array.isArray(appState)) {
|
|
92230
|
+
let loaded = 0;
|
|
92231
|
+
appState.forEach((cookie, index3) => {
|
|
92232
|
+
const str = cookieStringFromObject(cookie, index3);
|
|
92233
|
+
if (str.indexOf("=") <= 0) throw new Error(`Invalid appState cookie at index ${index3}.`);
|
|
92234
|
+
if (writeCookie(jar2, str)) loaded++;
|
|
92235
|
+
});
|
|
92236
|
+
return { source: "appState", loaded };
|
|
92237
|
+
}
|
|
92238
|
+
if (typeof appState === "string") {
|
|
92239
|
+
const parts = appState.split(";").map((s) => s.trim()).filter(Boolean);
|
|
92240
|
+
let loaded = 0;
|
|
92241
|
+
parts.forEach((str, index3) => {
|
|
92242
|
+
if (str.indexOf("=") <= 0) throw new Error(`Invalid appState cookie at index ${index3}.`);
|
|
92243
|
+
if (writeCookie(jar2, str)) loaded++;
|
|
92244
|
+
});
|
|
92245
|
+
return { source: "appStateString", loaded };
|
|
92246
|
+
}
|
|
92247
|
+
if (credentials.email && credentials.password) {
|
|
92248
|
+
const url2 = "https://api.facebook.com/method/auth.login";
|
|
92249
|
+
const params = {
|
|
92250
|
+
access_token: "350685531728|62f8ce9f74b12f84c123cc23437a4a32",
|
|
92251
|
+
format: "json",
|
|
92252
|
+
sdk_version: 2,
|
|
92253
|
+
email: credentials.email,
|
|
92254
|
+
locale: "en_US",
|
|
92255
|
+
password: credentials.password,
|
|
92256
|
+
generate_session_cookies: 1,
|
|
92257
|
+
sig: "c1c640010993db92e5afd11634ced864"
|
|
92258
|
+
};
|
|
92259
|
+
const xurl = `${url2}?${qs__default.default.stringify(params)}`;
|
|
92260
|
+
try {
|
|
92261
|
+
const legacyHeaders = getHeaders(url2, globalOptions, null, {
|
|
92262
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
92263
|
+
});
|
|
92264
|
+
const resp = await axios_default.get(xurl, {
|
|
92265
|
+
headers: legacyHeaders,
|
|
92266
|
+
timeout: 6e4,
|
|
92267
|
+
validateStatus: (status) => status >= 200 && status < 600
|
|
92268
|
+
});
|
|
92269
|
+
if (resp.status !== 200) throw new Error("Wrong password / email");
|
|
92270
|
+
const sessionCookies = resp.data["session_cookies"] || [];
|
|
92271
|
+
if (!sessionCookies.length) throw new Error("No session cookies returned");
|
|
92272
|
+
let loaded = 0;
|
|
92273
|
+
for (const c of sessionCookies) {
|
|
92274
|
+
const str = `${c.name}=${c.value}; domain=.facebook.com; path=/; Secure; SameSite=None`;
|
|
92275
|
+
try {
|
|
92276
|
+
jar2.setCookieSync(str, "https://facebook.com");
|
|
92277
|
+
loaded++;
|
|
92278
|
+
} catch {
|
|
92279
|
+
}
|
|
92280
|
+
}
|
|
92281
|
+
if (loaded === 0) throw new Error("No session cookies could be stored");
|
|
92282
|
+
return { source: "credentials", loaded };
|
|
92283
|
+
} catch (e) {
|
|
92284
|
+
throw new Error(e && e.message ? e.message : "Wrong password / email");
|
|
92285
|
+
}
|
|
92286
|
+
}
|
|
92287
|
+
throw new Error("No cookie or credentials found. Please provide cookies or credentials.");
|
|
92288
|
+
}
|
|
91842
92289
|
|
|
91843
92290
|
// src/deltas/apis/extra/addExternalModule.ts
|
|
91844
92291
|
function addExternalModule_default(defaultFuncs, api, ctx) {
|
|
@@ -100439,7 +100886,9 @@ var listenMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
100439
100886
|
attempts: 0,
|
|
100440
100887
|
delay: MQTT_CONFIG.INITIAL_RETRY_DELAY,
|
|
100441
100888
|
throttleDelay: MQTT_CONFIG.THROTTLE_DELAY,
|
|
100442
|
-
generation: 0
|
|
100889
|
+
generation: 0,
|
|
100890
|
+
health: null,
|
|
100891
|
+
healthSupervisor: null
|
|
100443
100892
|
};
|
|
100444
100893
|
const log2 = (...args) => log(...args);
|
|
100445
100894
|
function clearReconnectTimer() {
|
|
@@ -100453,6 +100902,13 @@ var listenMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
100453
100902
|
clearInterval(lifecycle.presenceInterval);
|
|
100454
100903
|
lifecycle.presenceInterval = null;
|
|
100455
100904
|
}
|
|
100905
|
+
if (lifecycle.healthSupervisor) {
|
|
100906
|
+
try {
|
|
100907
|
+
lifecycle.healthSupervisor.stop();
|
|
100908
|
+
} catch (_3) {
|
|
100909
|
+
}
|
|
100910
|
+
lifecycle.healthSupervisor = null;
|
|
100911
|
+
}
|
|
100456
100912
|
clearReconnectTimer();
|
|
100457
100913
|
}
|
|
100458
100914
|
function destroyClient() {
|
|
@@ -100580,6 +101036,8 @@ var listenMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
100580
101036
|
});
|
|
100581
101037
|
lifecycle.client = client2;
|
|
100582
101038
|
ctx.mqttClient = client2;
|
|
101039
|
+
const health = new RealtimeHealth();
|
|
101040
|
+
lifecycle.health = health;
|
|
100583
101041
|
let connected = false;
|
|
100584
101042
|
let closing = false;
|
|
100585
101043
|
let throttled = false;
|
|
@@ -100599,12 +101057,14 @@ var listenMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
100599
101057
|
if (generation !== lifecycle.generation) return;
|
|
100600
101058
|
connected = false;
|
|
100601
101059
|
ctx.mqttConnected = false;
|
|
101060
|
+
health.noteDisconnected();
|
|
100602
101061
|
});
|
|
100603
101062
|
client2.on("close", () => {
|
|
100604
101063
|
if (generation !== lifecycle.generation) return;
|
|
100605
101064
|
if (connected) log2("MQTT connection closed.");
|
|
100606
101065
|
connected = false;
|
|
100607
101066
|
ctx.mqttConnected = false;
|
|
101067
|
+
health.noteDisconnected();
|
|
100608
101068
|
if (closing) return;
|
|
100609
101069
|
closing = true;
|
|
100610
101070
|
if (authFailure) {
|
|
@@ -100622,6 +101082,7 @@ var listenMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
100622
101082
|
client2.on("connect", () => {
|
|
100623
101083
|
if (generation !== lifecycle.generation) return;
|
|
100624
101084
|
connected = true;
|
|
101085
|
+
health.noteConnected();
|
|
100625
101086
|
client2.subscribe(MQTT_TOPICS, (subErr) => {
|
|
100626
101087
|
if (subErr) {
|
|
100627
101088
|
error("Failed to subscribe to MQTT topics:", subErr);
|
|
@@ -100658,6 +101119,49 @@ var listenMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
100658
101119
|
ctx.mqttConnected = true;
|
|
100659
101120
|
ctx.lastMqttError = null;
|
|
100660
101121
|
resetBackoff();
|
|
101122
|
+
if (lifecycle.healthSupervisor) {
|
|
101123
|
+
try {
|
|
101124
|
+
lifecycle.healthSupervisor.stop();
|
|
101125
|
+
} catch (_3) {
|
|
101126
|
+
}
|
|
101127
|
+
}
|
|
101128
|
+
lifecycle.healthSupervisor = startRealtimeSupervisor({
|
|
101129
|
+
isConnected: () => generation === lifecycle.generation && client2.connected,
|
|
101130
|
+
reconnect: (reason) => {
|
|
101131
|
+
if (generation !== lifecycle.generation) return;
|
|
101132
|
+
if (lifecycle.stopped || ctx.loggedIn === false) return;
|
|
101133
|
+
log2(`MQTT ${reason}; recycling the socket`);
|
|
101134
|
+
try {
|
|
101135
|
+
client2.end(true);
|
|
101136
|
+
} catch (_3) {
|
|
101137
|
+
}
|
|
101138
|
+
const gen = generation;
|
|
101139
|
+
setTimeout(() => {
|
|
101140
|
+
if (gen !== lifecycle.generation) return;
|
|
101141
|
+
if (lifecycle.stopped || ctx.loggedIn === false) return;
|
|
101142
|
+
if (lifecycle.client && lifecycle.client.connected) return;
|
|
101143
|
+
if (lifecycle.reconnectTimer) return;
|
|
101144
|
+
scheduleReconnect("realtime socket recycled");
|
|
101145
|
+
}, 5e3).unref?.();
|
|
101146
|
+
},
|
|
101147
|
+
ping: () => {
|
|
101148
|
+
try {
|
|
101149
|
+
client2.ping();
|
|
101150
|
+
return true;
|
|
101151
|
+
} catch {
|
|
101152
|
+
return false;
|
|
101153
|
+
}
|
|
101154
|
+
},
|
|
101155
|
+
onVerdict: (state) => {
|
|
101156
|
+
if (state.verdict === "dead") {
|
|
101157
|
+
warn(
|
|
101158
|
+
"MQTT health",
|
|
101159
|
+
`silent for ${Math.round(state.sinceLastFrameMs / 1e3)}s; probing`
|
|
101160
|
+
);
|
|
101161
|
+
}
|
|
101162
|
+
}
|
|
101163
|
+
});
|
|
101164
|
+
ctx.__mqttHealth = () => lifecycle.health ? lifecycle.health.state(generation === lifecycle.generation && !!client2.connected) : null;
|
|
100661
101165
|
api.getBotInitialData().then((botData) => {
|
|
100662
101166
|
if (botData) {
|
|
100663
101167
|
log(`Logged in as: ${botData.name || "Facebook User"} (${botData.uid || ctx.userID})`);
|
|
@@ -100668,6 +101172,7 @@ var listenMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
100668
101172
|
});
|
|
100669
101173
|
client2.on("message", async (topic, message, _packet) => {
|
|
100670
101174
|
try {
|
|
101175
|
+
health.noteFrame();
|
|
100671
101176
|
ctx.lastMessageTime = Date.now();
|
|
100672
101177
|
ctx.messageCount = (ctx.messageCount || 0) + 1;
|
|
100673
101178
|
const jsonMessage = JSON.parse(message.toString());
|
|
@@ -100753,6 +101258,16 @@ var listenMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
100753
101258
|
this.stop();
|
|
100754
101259
|
if (typeof cb === "function") cb();
|
|
100755
101260
|
}
|
|
101261
|
+
/** Live connection-health snapshot, for diagnostics/alerting. */
|
|
101262
|
+
getHealth() {
|
|
101263
|
+
if (!lifecycle.health) return null;
|
|
101264
|
+
const connected = !lifecycle.stopped && !!lifecycle.client && !!lifecycle.client.connected;
|
|
101265
|
+
return lifecycle.health.state(connected);
|
|
101266
|
+
}
|
|
101267
|
+
/** Is this listener currently stopped? */
|
|
101268
|
+
isStopped() {
|
|
101269
|
+
return lifecycle.stopped;
|
|
101270
|
+
}
|
|
100756
101271
|
}
|
|
100757
101272
|
const msgEmitter = new MessageEmitter();
|
|
100758
101273
|
lifecycle.stopped = false;
|
|
@@ -100921,76 +101436,8 @@ async function loginHelper(credentials, globalOptions, callback, setOptionsFunc,
|
|
|
100921
101436
|
const jar2 = getJar();
|
|
100922
101437
|
log("Logging in...");
|
|
100923
101438
|
const appState = credentials.appState;
|
|
100924
|
-
if (appState) {
|
|
100925
|
-
|
|
100926
|
-
if (Array.isArray(appState)) {
|
|
100927
|
-
cookieStrings = appState.map((c, index3) => {
|
|
100928
|
-
const name = c && (c.name || c.key);
|
|
100929
|
-
if (!name || c.value === void 0 || c.value === null) {
|
|
100930
|
-
throw new Error(`Invalid appState cookie at index ${index3}.`);
|
|
100931
|
-
}
|
|
100932
|
-
return formatAppStateCookie(c);
|
|
100933
|
-
});
|
|
100934
|
-
} else if (typeof appState === "string") {
|
|
100935
|
-
cookieStrings = appState.split(";").map((s) => s.trim()).filter(Boolean);
|
|
100936
|
-
} else {
|
|
100937
|
-
throw new Error(
|
|
100938
|
-
"Invalid appState format. Please provide an array of cookie objects or a cookie string."
|
|
100939
|
-
);
|
|
100940
|
-
}
|
|
100941
|
-
cookieStrings.forEach((cookieString, index3) => {
|
|
100942
|
-
if (cookieString.indexOf("=") <= 0) {
|
|
100943
|
-
throw new Error(`Invalid appState cookie at index ${index3}.`);
|
|
100944
|
-
}
|
|
100945
|
-
const normalized = cookieString.replace(/;\s*domain=facebook\.com/i, "; domain=.facebook.com").replace(/;\s*domain=messenger\.com/i, "; domain=.messenger.com");
|
|
100946
|
-
const str = /(^|;)\s*domain=/i.test(normalized) ? normalized : `${normalized}; domain=.facebook.com; path=/; Secure; SameSite=None`;
|
|
100947
|
-
try {
|
|
100948
|
-
jar2.setCookieSync(str, "https://facebook.com");
|
|
100949
|
-
} catch {
|
|
100950
|
-
try {
|
|
100951
|
-
jar2.setCookieSync(`${normalized}; domain=.facebook.com; path=/; Secure; SameSite=None`, "https://www.facebook.com");
|
|
100952
|
-
} catch {
|
|
100953
|
-
}
|
|
100954
|
-
}
|
|
100955
|
-
});
|
|
100956
|
-
} else if (credentials.email && credentials.password) {
|
|
100957
|
-
const url2 = "https://api.facebook.com/method/auth.login";
|
|
100958
|
-
const params = {
|
|
100959
|
-
access_token: "350685531728|62f8ce9f74b12f84c123cc23437a4a32",
|
|
100960
|
-
format: "json",
|
|
100961
|
-
sdk_version: 2,
|
|
100962
|
-
email: credentials.email,
|
|
100963
|
-
locale: "en_US",
|
|
100964
|
-
password: credentials.password,
|
|
100965
|
-
generate_session_cookies: 1,
|
|
100966
|
-
sig: "c1c640010993db92e5afd11634ced864"
|
|
100967
|
-
};
|
|
100968
|
-
const query = qs__default.default.stringify(params);
|
|
100969
|
-
const xurl = `${url2}?${query}`;
|
|
100970
|
-
try {
|
|
100971
|
-
const legacyHeaders = getHeaders(
|
|
100972
|
-
url2,
|
|
100973
|
-
globalOptions,
|
|
100974
|
-
null,
|
|
100975
|
-
{ "Content-Type": "application/x-www-form-urlencoded" }
|
|
100976
|
-
);
|
|
100977
|
-
const resp2 = await axios_default.get(xurl, {
|
|
100978
|
-
headers: legacyHeaders,
|
|
100979
|
-
timeout: 6e4,
|
|
100980
|
-
validateStatus: (status) => status >= 200 && status < 600
|
|
100981
|
-
});
|
|
100982
|
-
if (resp2.status !== 200) {
|
|
100983
|
-
throw new Error("Wrong password / email");
|
|
100984
|
-
}
|
|
100985
|
-
const cstrs = resp2.data["session_cookies"].map((c) => `${c.name}=${c.value}`);
|
|
100986
|
-
cstrs.forEach((cstr) => {
|
|
100987
|
-
const domain = ".facebook.com";
|
|
100988
|
-
const str = `${cstr}; domain=${domain}; path=/; Secure; SameSite=None`;
|
|
100989
|
-
jar2.setCookieSync(str, "https://facebook.com");
|
|
100990
|
-
});
|
|
100991
|
-
} catch (e) {
|
|
100992
|
-
throw new Error("Wrong password / email");
|
|
100993
|
-
}
|
|
101439
|
+
if (appState || credentials.email && credentials.password) {
|
|
101440
|
+
await acquireCookies(jar2, credentials, globalOptions);
|
|
100994
101441
|
} else {
|
|
100995
101442
|
throw new Error("No cookie or credentials found. Please provide cookies or credentials.");
|
|
100996
101443
|
}
|
|
@@ -101129,6 +101576,81 @@ async function loginHelper(credentials, globalOptions, callback, setOptionsFunc,
|
|
|
101129
101576
|
}
|
|
101130
101577
|
}
|
|
101131
101578
|
ctx.__stopCookieKeepAlive = scheduleSessionKeepAlive(ctx, defaultFuncs, 15 * 60 * 1e3);
|
|
101579
|
+
ctx.__credentials = {
|
|
101580
|
+
email: credentials.email,
|
|
101581
|
+
password: credentials.password
|
|
101582
|
+
};
|
|
101583
|
+
ctx.__loginGlobalOptions = globalOptions;
|
|
101584
|
+
ctx.__persistPath = globalOptions.appStatePath;
|
|
101585
|
+
if (globalOptions.recovery !== false) {
|
|
101586
|
+
const recoveryOptions = typeof globalOptions.recovery === "object" ? globalOptions.recovery : {};
|
|
101587
|
+
const supervisor = startRecovery(
|
|
101588
|
+
ctx,
|
|
101589
|
+
{
|
|
101590
|
+
ctx,
|
|
101591
|
+
isAuthenticated: () => hasAuthenticatedSession(ctx.jar),
|
|
101592
|
+
probeLiveness: async () => {
|
|
101593
|
+
try {
|
|
101594
|
+
const res = await defaultFuncs.get(
|
|
101595
|
+
"https://www.facebook.com/",
|
|
101596
|
+
ctx.jar,
|
|
101597
|
+
null,
|
|
101598
|
+
ctx.globalOptions,
|
|
101599
|
+
{ noRef: true }
|
|
101600
|
+
);
|
|
101601
|
+
const html3 = typeof res === "string" ? res : res && res.body;
|
|
101602
|
+
if (typeof html3 !== "string" || !html3) return true;
|
|
101603
|
+
return !isLoggedOutDocument(html3);
|
|
101604
|
+
} catch {
|
|
101605
|
+
return true;
|
|
101606
|
+
}
|
|
101607
|
+
},
|
|
101608
|
+
refresh: () => repairSession(ctx, defaultFuncs),
|
|
101609
|
+
canRelogin: Boolean(credentials.email && credentials.password),
|
|
101610
|
+
relogin: async () => {
|
|
101611
|
+
if (!credentials.email || !credentials.password) return null;
|
|
101612
|
+
await sleep(retryDelay(0, 2e3, 15e3));
|
|
101613
|
+
await acquireCookies(ctx.jar, credentials, globalOptions);
|
|
101614
|
+
await repairSession(ctx, defaultFuncs);
|
|
101615
|
+
if (!hasAuthenticatedSession(ctx.jar)) return null;
|
|
101616
|
+
return getAppState(ctx.jar);
|
|
101617
|
+
},
|
|
101618
|
+
persistAppState: (state) => {
|
|
101619
|
+
const path2 = globalOptions.appStatePath;
|
|
101620
|
+
if (!path2) return;
|
|
101621
|
+
try {
|
|
101622
|
+
const fs2 = __require("fs");
|
|
101623
|
+
fs2.writeFileSync(path2, JSON.stringify(state, null, 2));
|
|
101624
|
+
log(`Recovery: refreshed appState written to ${path2}`);
|
|
101625
|
+
} catch (persistError) {
|
|
101626
|
+
warn("Recovery: could not persist appState:", persistError?.message);
|
|
101627
|
+
}
|
|
101628
|
+
},
|
|
101629
|
+
restartMqtt: () => {
|
|
101630
|
+
try {
|
|
101631
|
+
if (typeof ctx.__restartMqtt === "function") {
|
|
101632
|
+
ctx.__restartMqtt();
|
|
101633
|
+
} else if (typeof ctx.reconnectMqtt === "function" && activeListener) {
|
|
101634
|
+
void ctx.reconnectMqtt();
|
|
101635
|
+
}
|
|
101636
|
+
} catch {
|
|
101637
|
+
}
|
|
101638
|
+
},
|
|
101639
|
+
onEvent: (event) => {
|
|
101640
|
+
if (event.type === "gave-up") {
|
|
101641
|
+
warn("Recovery", event.detail);
|
|
101642
|
+
} else if (event.type === "relogin" || event.type === "healed") {
|
|
101643
|
+
log(`Recovery: ${event.detail}`);
|
|
101644
|
+
}
|
|
101645
|
+
}
|
|
101646
|
+
},
|
|
101647
|
+
recoveryOptions
|
|
101648
|
+
);
|
|
101649
|
+
api.getRecoveryState = () => supervisor.snapshot();
|
|
101650
|
+
api.checkRecoveryNow = () => supervisor.checkNow();
|
|
101651
|
+
api.stopRecovery = () => supervisor.stop();
|
|
101652
|
+
api.startRecovery = () => supervisor.start();
|
|
101653
|
+
}
|
|
101132
101654
|
if (globalOptions.liveness !== false) {
|
|
101133
101655
|
const liveness = startLiveness(ctx, {
|
|
101134
101656
|
foregroundPing: () => log("Session active"),
|
|
@@ -101311,6 +101833,11 @@ lodash/lodash.js:
|
|
|
101311
101833
|
*)
|
|
101312
101834
|
*/
|
|
101313
101835
|
|
|
101836
|
+
exports.PING_GRACE_MS = PING_GRACE_MS;
|
|
101837
|
+
exports.RealtimeHealth = RealtimeHealth;
|
|
101838
|
+
exports.RecoverySupervisor = RecoverySupervisor;
|
|
101839
|
+
exports.SILENT_WINDOW_MS = SILENT_WINDOW_MS;
|
|
101840
|
+
exports.acquireCookies = acquireCookies;
|
|
101314
101841
|
exports.applySetCookie = applySetCookie;
|
|
101315
101842
|
exports.awaitProactiveSlot = awaitProactiveSlot;
|
|
101316
101843
|
exports.canActProactively = canActProactively;
|
|
@@ -101330,6 +101857,7 @@ exports.humanDelay = humanDelay;
|
|
|
101330
101857
|
exports.invalidateCometTokens = invalidateCometTokens;
|
|
101331
101858
|
exports.isAuthFailure = isAuthFailure;
|
|
101332
101859
|
exports.isBreakerOpen = isBreakerOpen;
|
|
101860
|
+
exports.isLoggedOutDocument = isLoggedOutDocument;
|
|
101333
101861
|
exports.isStaleTokenError = isStaleTokenError;
|
|
101334
101862
|
exports.login = login;
|
|
101335
101863
|
exports.missingSessionCookies = missingSessionCookies;
|
|
@@ -101350,6 +101878,8 @@ exports.retryDelay = retryDelay;
|
|
|
101350
101878
|
exports.safetySnapshot = safetySnapshot;
|
|
101351
101879
|
exports.sleep = sleep;
|
|
101352
101880
|
exports.startLiveness = startLiveness;
|
|
101881
|
+
exports.startRealtimeSupervisor = startRealtimeSupervisor;
|
|
101882
|
+
exports.startRecovery = startRecovery;
|
|
101353
101883
|
exports.tripBreaker = tripBreaker;
|
|
101354
101884
|
exports.warmUpSession = warmUpSession;
|
|
101355
101885
|
exports.withCometTokens = withCometTokens;
|