@dongdev/fca-unofficial 3.0.9 → 3.0.11
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 +6 -0
- package/module/loginHelper.js +92 -38
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/module/loginHelper.js
CHANGED
|
@@ -281,11 +281,15 @@ function sort(obj) {
|
|
|
281
281
|
async function setJarCookies(j, appstate) {
|
|
282
282
|
const tasks = [];
|
|
283
283
|
for (const c of appstate) {
|
|
284
|
+
const cookieName = c.name || c.key;
|
|
285
|
+
const cookieValue = c.value;
|
|
286
|
+
if (!cookieName || cookieValue === undefined) continue;
|
|
284
287
|
const dom = (c.domain || ".facebook.com").replace(/^\./, "");
|
|
285
288
|
const path = c.path || "/";
|
|
286
289
|
const base1 = `https://${dom}${path}`;
|
|
287
290
|
const base2 = `https://www.${dom}${path}`;
|
|
288
|
-
const
|
|
291
|
+
const domain = c.domain || ".facebook.com";
|
|
292
|
+
const str = `${cookieName}=${cookieValue}; Domain=${domain}; Path=${path};`;
|
|
289
293
|
tasks.push(j.setCookie(str, base1));
|
|
290
294
|
tasks.push(j.setCookie(str, base2));
|
|
291
295
|
}
|
|
@@ -471,13 +475,30 @@ async function tryAutoLoginIfNeeded(currentHtml, currentCookies, globalOptions,
|
|
|
471
475
|
cs.find(c => c.key === "c_user")?.value ||
|
|
472
476
|
cs.find(c => c.name === "i_user")?.value ||
|
|
473
477
|
cs.find(c => c.name === "c_user")?.value;
|
|
478
|
+
const htmlUID = body => {
|
|
479
|
+
const s = typeof body === "string" ? body : String(body ?? "");
|
|
480
|
+
return s.match(/"USER_ID"\s*:\s*"(\d+)"/)?.[1] || s.match(/\["CurrentUserInitialData",\[\],\{.*?"USER_ID":"(\d+)".*?\},\d+\]/)?.[1];
|
|
481
|
+
};
|
|
474
482
|
let userID = getUID(currentCookies);
|
|
483
|
+
// Also try to extract userID from HTML if not found in cookies
|
|
484
|
+
if (!userID) {
|
|
485
|
+
userID = htmlUID(currentHtml);
|
|
486
|
+
}
|
|
475
487
|
if (userID) return { html: currentHtml, cookies: currentCookies, userID };
|
|
476
488
|
// If appState/Cookie was provided and is not dead (not checkpointed), skip backup
|
|
477
489
|
if (hadAppStateInput) {
|
|
478
490
|
const isCheckpoint = currentHtml.includes("/checkpoint/block/?next");
|
|
479
491
|
if (!isCheckpoint) {
|
|
480
|
-
// AppState provided and not checkpointed,
|
|
492
|
+
// AppState provided and not checkpointed, but userID not found
|
|
493
|
+
// This might be a temporary issue - try to refresh cookies from jar
|
|
494
|
+
try {
|
|
495
|
+
const refreshedCookies = await Promise.resolve(jar.getCookies("https://www.facebook.com"));
|
|
496
|
+
userID = getUID(refreshedCookies);
|
|
497
|
+
if (userID) {
|
|
498
|
+
return { html: currentHtml, cookies: refreshedCookies, userID };
|
|
499
|
+
}
|
|
500
|
+
} catch { }
|
|
501
|
+
// If still no userID, skip backup and throw error
|
|
481
502
|
throw new Error("Missing user cookie from provided appState");
|
|
482
503
|
}
|
|
483
504
|
// AppState is dead (checkpointed), proceed to backup/email login
|
|
@@ -533,41 +554,61 @@ function makeLogin(j, email, password, globalOptions) {
|
|
|
533
554
|
function loginHelper(appState, Cookie, email, password, globalOptions, callback) {
|
|
534
555
|
try {
|
|
535
556
|
const domain = ".facebook.com";
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
557
|
+
// Helper to extract userID from appState input
|
|
558
|
+
const extractUIDFromAppState = (appStateInput) => {
|
|
559
|
+
if (!appStateInput) return null;
|
|
560
|
+
let parsed = appStateInput;
|
|
561
|
+
if (typeof appStateInput === "string") {
|
|
562
|
+
try {
|
|
563
|
+
parsed = JSON.parse(appStateInput);
|
|
564
|
+
} catch {
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
if (Array.isArray(parsed)) {
|
|
569
|
+
const cUser = parsed.find(c => (c.key === "c_user" || c.name === "c_user"));
|
|
570
|
+
if (cUser) return cUser.value;
|
|
571
|
+
const iUser = parsed.find(c => (c.key === "i_user" || c.name === "i_user"));
|
|
572
|
+
if (iUser) return iUser.value;
|
|
573
|
+
}
|
|
574
|
+
return null;
|
|
575
|
+
};
|
|
576
|
+
let userIDFromAppState = extractUIDFromAppState(appState);
|
|
577
|
+
(async () => {
|
|
578
|
+
try {
|
|
579
|
+
if (appState) {
|
|
580
|
+
if (typeof appState === "string") {
|
|
581
|
+
let parsed = appState;
|
|
582
|
+
try {
|
|
583
|
+
parsed = JSON.parse(appState);
|
|
584
|
+
} catch { }
|
|
585
|
+
if (Array.isArray(parsed)) {
|
|
586
|
+
// Use setJarCookies to properly handle individual cookie domains/paths
|
|
587
|
+
await setJarCookies(jar, parsed);
|
|
588
|
+
} else if (typeof parsed === "string") {
|
|
589
|
+
const pairs = normalizeCookieHeaderString(parsed);
|
|
590
|
+
if (!pairs.length) throw new Error("Empty appState cookie header");
|
|
591
|
+
setJarFromPairs(jar, pairs, domain);
|
|
592
|
+
} else {
|
|
593
|
+
throw new Error("Invalid appState format");
|
|
594
|
+
}
|
|
595
|
+
} else if (Array.isArray(appState)) {
|
|
596
|
+
// Use setJarCookies to properly handle individual cookie domains/paths
|
|
597
|
+
await setJarCookies(jar, appState);
|
|
550
598
|
} else {
|
|
551
599
|
throw new Error("Invalid appState format");
|
|
552
600
|
}
|
|
553
|
-
} else if (Array.isArray(appState)) {
|
|
554
|
-
const pairs = appState.map(c => [c.name || c.key, c.value].join("="));
|
|
555
|
-
setJarFromPairs(jar, pairs, domain);
|
|
556
|
-
} else {
|
|
557
|
-
throw new Error("Invalid appState format");
|
|
558
601
|
}
|
|
602
|
+
if (Cookie) {
|
|
603
|
+
let cookiePairs = [];
|
|
604
|
+
if (typeof Cookie === "string") cookiePairs = normalizeCookieHeaderString(Cookie);
|
|
605
|
+
else if (Array.isArray(Cookie)) cookiePairs = Cookie.map(String).filter(Boolean);
|
|
606
|
+
else if (Cookie && typeof Cookie === "object") cookiePairs = Object.entries(Cookie).map(([k, v]) => `${k}=${v}`);
|
|
607
|
+
if (cookiePairs.length) setJarFromPairs(jar, cookiePairs, domain);
|
|
608
|
+
}
|
|
609
|
+
} catch (e) {
|
|
610
|
+
return callback(e);
|
|
559
611
|
}
|
|
560
|
-
if (Cookie) {
|
|
561
|
-
let cookiePairs = [];
|
|
562
|
-
if (typeof Cookie === "string") cookiePairs = normalizeCookieHeaderString(Cookie);
|
|
563
|
-
else if (Array.isArray(Cookie)) cookiePairs = Cookie.map(String).filter(Boolean);
|
|
564
|
-
else if (Cookie && typeof Cookie === "object") cookiePairs = Object.entries(Cookie).map(([k, v]) => `${k}=${v}`);
|
|
565
|
-
if (cookiePairs.length) setJarFromPairs(jar, cookiePairs, domain);
|
|
566
|
-
}
|
|
567
|
-
} catch (e) {
|
|
568
|
-
return callback(e);
|
|
569
|
-
}
|
|
570
|
-
(async () => {
|
|
571
612
|
const ctx = { globalOptions, options: globalOptions, reconnectAttempts: 0 };
|
|
572
613
|
ctx.bypassAutomation = async function (resp, j) {
|
|
573
614
|
global.fca = global.fca || {};
|
|
@@ -682,13 +723,26 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
|
|
|
682
723
|
const processed = (await ctx.bypassAutomation(res, jar)) || res;
|
|
683
724
|
let html = processed && processed.data ? processed.data : "";
|
|
684
725
|
let cookies = await Promise.resolve(jar.getCookies("https://www.facebook.com"));
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
726
|
+
const getUIDFromCookies = cs =>
|
|
727
|
+
cs.find(c => c.key === "i_user")?.value ||
|
|
728
|
+
cs.find(c => c.key === "c_user")?.value ||
|
|
729
|
+
cs.find(c => c.name === "i_user")?.value ||
|
|
730
|
+
cs.find(c => c.name === "c_user")?.value;
|
|
731
|
+
const getUIDFromHTML = body => {
|
|
732
|
+
const s = typeof body === "string" ? body : String(body ?? "");
|
|
733
|
+
return s.match(/"USER_ID"\s*:\s*"(\d+)"/)?.[1] || s.match(/\["CurrentUserInitialData",\[\],\{.*?"USER_ID":"(\d+)".*?\},\d+\]/)?.[1];
|
|
734
|
+
};
|
|
735
|
+
let userID = getUIDFromCookies(cookies);
|
|
736
|
+
// Also try to extract userID from HTML if not found in cookies
|
|
737
|
+
if (!userID) {
|
|
738
|
+
userID = getUIDFromHTML(html);
|
|
739
|
+
}
|
|
740
|
+
// If still not found and appState was provided, use userID from appState input as fallback
|
|
741
|
+
if (!userID && userIDFromAppState) {
|
|
742
|
+
userID = userIDFromAppState;
|
|
743
|
+
}
|
|
690
744
|
if (!userID) {
|
|
691
|
-
// Pass
|
|
745
|
+
// Pass hadAppStateInput=true if appState/Cookie was originally provided
|
|
692
746
|
const retried = await tryAutoLoginIfNeeded(html, cookies, globalOptions, ctx, !!(appState || Cookie));
|
|
693
747
|
html = retried.html;
|
|
694
748
|
cookies = retried.cookies;
|
package/package.json
CHANGED