@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 CHANGED
@@ -155,3 +155,9 @@ Too lazy to write changelog, sorry! (will write changelog in the next release, t
155
155
 
156
156
  ## v3.0.8 - 2025-11-27
157
157
  - Hotfix / auto bump
158
+
159
+ ## v3.0.9 - 2025-12-05
160
+ - Hotfix / auto bump
161
+
162
+ ## v3.0.10 - 2025-12-05
163
+ - Hotfix / auto bump
@@ -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 str = `${c.key}=${c.value}; Domain=${c.domain || ".facebook.com"}; Path=${path};`;
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, skip backup - just throw error
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
- try {
537
- if (appState) {
538
- if (typeof appState === "string") {
539
- let parsed = appState;
540
- try {
541
- parsed = JSON.parse(appState);
542
- } catch { }
543
- if (Array.isArray(parsed)) {
544
- const pairs = parsed.map(c => [c.name || c.key, c.value].join("="));
545
- setJarFromPairs(jar, pairs, domain);
546
- } else if (typeof parsed === "string") {
547
- const pairs = normalizeCookieHeaderString(parsed);
548
- if (!pairs.length) throw new Error("Empty appState cookie header");
549
- setJarFromPairs(jar, pairs, domain);
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
- let userID =
686
- cookies.find(c => c.key === "i_user")?.value ||
687
- cookies.find(c => c.key === "c_user")?.value ||
688
- cookies.find(c => c.name === "i_user")?.value ||
689
- cookies.find(c => c.name === "c_user")?.value;
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 skipBackup=true if appState/Cookie was originally provided
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dongdev/fca-unofficial",
3
- "version": "3.0.9",
3
+ "version": "3.0.11",
4
4
  "description": "Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",