@dongdev/fca-unofficial 4.0.2 → 4.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/README.md CHANGED
@@ -268,7 +268,9 @@ When `stopOnSignals` is `true`, the bot automatically calls `stop()` on `SIGINT`
268
268
 
269
269
  ## Configuration
270
270
 
271
- Copy the example config and edit it:
271
+ If `fca-config.json` is missing in the process working directory, it is **created automatically** with defaults on first load (or in-memory defaults only if the file cannot be written).
272
+
273
+ You can also copy the example and edit it:
272
274
 
273
275
  ```bash
274
276
  cp fca-config.example.json fca-config.json
package/dist/index.d.mts CHANGED
@@ -313,6 +313,13 @@ interface FcaConfig {
313
313
  token: string;
314
314
  autoReconnect: boolean;
315
315
  };
316
+ /** SQLite thread row cache used by `getThreadInfo`. */
317
+ threadCache: {
318
+ /** Treat DB row as fresh for this many ms (default 15 minutes). */
319
+ maxAgeMs: number;
320
+ /** Clear `data` for all threads on this interval so the next `getThreadInfo` refetches; 0 = off. */
321
+ invalidateIntervalMs: number;
322
+ };
316
323
  [key: string]: Loose;
317
324
  }
318
325
  interface LoadedFcaConfig {
package/dist/index.d.ts CHANGED
@@ -313,6 +313,13 @@ interface FcaConfig {
313
313
  token: string;
314
314
  autoReconnect: boolean;
315
315
  };
316
+ /** SQLite thread row cache used by `getThreadInfo`. */
317
+ threadCache: {
318
+ /** Treat DB row as fresh for this many ms (default 15 minutes). */
319
+ maxAgeMs: number;
320
+ /** Clear `data` for all threads on this interval so the next `getThreadInfo` refetches; 0 = off. */
321
+ invalidateIntervalMs: number;
322
+ };
316
323
  [key: string]: Loose;
317
324
  }
318
325
  interface LoadedFcaConfig {
package/dist/index.js CHANGED
@@ -1464,7 +1464,7 @@ function attachThreadUpdater(ctx, models2, logger) {
1464
1464
  await Thread2.create({
1465
1465
  threadID: id,
1466
1466
  messageCount: 1,
1467
- data: { threadID: id }
1467
+ data: null
1468
1468
  });
1469
1469
  } catch {
1470
1470
  }
@@ -15449,6 +15449,7 @@ function resolveConfig(input) {
15449
15449
  config2.mqtt = deepMerge(defaultConfig.mqtt, config2.mqtt || {});
15450
15450
  config2.antiGetInfo = deepMerge(defaultConfig.antiGetInfo, config2.antiGetInfo || {});
15451
15451
  config2.remoteControl = deepMerge(defaultConfig.remoteControl, config2.remoteControl || {});
15452
+ config2.threadCache = deepMerge(defaultConfig.threadCache, config2.threadCache || {});
15452
15453
  config2.checkUpdate = deepMerge(defaultConfig.checkUpdate, config2.checkUpdate || {});
15453
15454
  config2.autoLogin = normalizeBoolean(config2.autoLogin, defaultConfig.autoLogin);
15454
15455
  config2.autoUpdate = normalizeBoolean(rawInput.autoUpdate, defaultConfig.autoUpdate);
@@ -15497,6 +15498,17 @@ function resolveConfig(input) {
15497
15498
  1e3,
15498
15499
  normalizeNumber(config2.checkUpdate.timeoutMs, defaultConfig.checkUpdate.timeoutMs)
15499
15500
  );
15501
+ config2.threadCache.maxAgeMs = Math.max(
15502
+ 0,
15503
+ normalizeNumber(config2.threadCache.maxAgeMs, defaultConfig.threadCache.maxAgeMs)
15504
+ );
15505
+ config2.threadCache.invalidateIntervalMs = Math.max(
15506
+ 0,
15507
+ normalizeNumber(
15508
+ config2.threadCache.invalidateIntervalMs,
15509
+ defaultConfig.threadCache.invalidateIntervalMs
15510
+ )
15511
+ );
15500
15512
  config2.autoUpdate = config2.checkUpdate.enabled;
15501
15513
  return config2;
15502
15514
  }
@@ -15506,6 +15518,21 @@ function getConfigPath() {
15506
15518
  function loadConfig() {
15507
15519
  const configPath = getConfigPath();
15508
15520
  if (!import_node_fs.default.existsSync(configPath)) {
15521
+ try {
15522
+ const resolved = resolveConfig(defaultConfig);
15523
+ const payload = `${JSON.stringify(resolved, null, 2)}
15524
+ `;
15525
+ import_node_fs.default.writeFileSync(configPath, payload, "utf8");
15526
+ logger_default(`Created ${import_node_path.default.basename(configPath)} in ${process.cwd()} (defaults).`, "info");
15527
+ return {
15528
+ config: resolved,
15529
+ configPath,
15530
+ exists: true
15531
+ };
15532
+ } catch (err) {
15533
+ const msg = err && err.message ? err.message : String(err);
15534
+ logger_default(`Could not create fca-config.json (${msg}). Using in-memory defaults.`, "warn");
15535
+ }
15509
15536
  return {
15510
15537
  config: resolveConfig(defaultConfig),
15511
15538
  configPath,
@@ -15555,8 +15582,8 @@ var init_config2 = __esm({
15555
15582
  autoUpdate: true,
15556
15583
  checkUpdate: {
15557
15584
  enabled: true,
15558
- install: false,
15559
- notifyIfCurrent: false,
15585
+ install: true,
15586
+ notifyIfCurrent: true,
15560
15587
  packageName: DEFAULT_PACKAGE_NAME,
15561
15588
  registryUrl: DEFAULT_REGISTRY_URL,
15562
15589
  timeoutMs: 1e4
@@ -15575,6 +15602,10 @@ var init_config2 = __esm({
15575
15602
  url: "",
15576
15603
  token: "",
15577
15604
  autoReconnect: true
15605
+ },
15606
+ threadCache: {
15607
+ maxAgeMs: 9e5,
15608
+ invalidateIntervalMs: 9e5
15578
15609
  }
15579
15610
  };
15580
15611
  }
@@ -15586,7 +15617,7 @@ var init_package = __esm({
15586
15617
  "package.json"() {
15587
15618
  package_default = {
15588
15619
  name: "@dongdev/fca-unofficial",
15589
- version: "4.0.2",
15620
+ version: "4.0.3",
15590
15621
  description: "Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically",
15591
15622
  main: "dist/cjs.cjs",
15592
15623
  types: "dist/index.d.ts",
@@ -15729,8 +15760,8 @@ function readUpdateConfig(input) {
15729
15760
  }
15730
15761
  const fallback = {
15731
15762
  enabled: true,
15732
- install: false,
15733
- notifyIfCurrent: false,
15763
+ install: true,
15764
+ notifyIfCurrent: true,
15734
15765
  packageName: package_default.name,
15735
15766
  registryUrl: package_default.publishConfig?.registry || "https://registry.npmjs.org",
15736
15767
  timeoutMs: 1e4
@@ -20692,6 +20723,34 @@ var init_threadData = __esm({
20692
20723
  });
20693
20724
 
20694
20725
  // src/domains/threads/queries/get-thread-info.ts
20726
+ function getThreadCacheMaxAgeMs() {
20727
+ try {
20728
+ const cfg2 = globalThis.fca?.config;
20729
+ const ms = cfg2?.threadCache?.maxAgeMs;
20730
+ if (typeof ms === "number" && Number.isFinite(ms) && ms > 0) {
20731
+ return ms;
20732
+ }
20733
+ } catch {
20734
+ }
20735
+ return DEFAULT_CACHE_MAX_AGE_MS;
20736
+ }
20737
+ function isUsableThreadInfoCache(data) {
20738
+ if (data == null || typeof data !== "object" || Array.isArray(data)) {
20739
+ return false;
20740
+ }
20741
+ const o = data;
20742
+ const keys = Object.keys(o);
20743
+ if (keys.length === 0) {
20744
+ return false;
20745
+ }
20746
+ if (keys.length === 1 && keys[0] === "threadID") {
20747
+ return false;
20748
+ }
20749
+ if (!Array.isArray(o.participantIDs)) {
20750
+ return false;
20751
+ }
20752
+ return true;
20753
+ }
20695
20754
  function formatEventReminders(reminder) {
20696
20755
  return {
20697
20756
  reminderID: reminder.id,
@@ -20810,7 +20869,6 @@ function createGetThreadInfoQuery(deps) {
20810
20869
  const { defaultFuncs, api, ctx, logError: logError2 } = deps;
20811
20870
  const threadData = createThreadData(api);
20812
20871
  const { create, get: get3, update } = threadData || {};
20813
- const FRESH_MS = 10 * 60 * 1e3;
20814
20872
  async function loadFromDb(ids) {
20815
20873
  if (!threadData || typeof get3 !== "function") {
20816
20874
  return { fresh: {}, stale: ids };
@@ -20819,12 +20877,13 @@ function createGetThreadInfoQuery(deps) {
20819
20877
  const stale = [];
20820
20878
  const rows = await Promise.all(ids.map((id) => get3(id).catch(() => null)));
20821
20879
  const now = Date.now();
20880
+ const maxAgeMs = getThreadCacheMaxAgeMs();
20822
20881
  for (let index = 0; index < ids.length; index += 1) {
20823
20882
  const id = ids[index];
20824
20883
  const row = rows[index];
20825
- if (row?.data) {
20884
+ if (row?.data != null && isUsableThreadInfoCache(row.data)) {
20826
20885
  const updatedAt = row.updatedAt ? new Date(row.updatedAt).getTime() : 0;
20827
- if (updatedAt && now - updatedAt <= FRESH_MS) {
20886
+ if (updatedAt && now - updatedAt <= maxAgeMs) {
20828
20887
  fresh[id] = row.data;
20829
20888
  } else {
20830
20889
  stale.push(id);
@@ -20923,12 +20982,14 @@ function createGetThreadInfoQuery(deps) {
20923
20982
  return promise;
20924
20983
  };
20925
20984
  }
20985
+ var DEFAULT_CACHE_MAX_AGE_MS;
20926
20986
  var init_get_thread_info = __esm({
20927
20987
  "src/domains/threads/queries/get-thread-info.ts"() {
20928
20988
  "use strict";
20929
20989
  init_legacy_promise();
20930
20990
  init_graphql();
20931
20991
  init_threadData();
20992
+ DEFAULT_CACHE_MAX_AGE_MS = 15 * 60 * 1e3;
20932
20993
  }
20933
20994
  });
20934
20995
 
@@ -25777,6 +25838,32 @@ var init_mqtt = __esm({
25777
25838
  }
25778
25839
  });
25779
25840
 
25841
+ // src/core/thread-cache-periodic.ts
25842
+ function attachThreadCachePeriodicInvalidate(ctx, models2, _logger, cfg2) {
25843
+ const Thread2 = models2?.Thread;
25844
+ if (!Thread2 || typeof Thread2.update !== "function") {
25845
+ return;
25846
+ }
25847
+ const threadUpdate = Thread2.update;
25848
+ const intervalMs = cfg2.threadCache?.invalidateIntervalMs ?? 0;
25849
+ if (!intervalMs || intervalMs < 6e4) {
25850
+ return;
25851
+ }
25852
+ const prev = ctx._threadCacheInvalidateTimer;
25853
+ if (prev != null && typeof clearInterval === "function") {
25854
+ clearInterval(prev);
25855
+ }
25856
+ ctx._threadCacheInvalidateTimer = setInterval(() => {
25857
+ void threadUpdate({ data: null }, { where: {} }).catch(() => {
25858
+ });
25859
+ }, intervalMs);
25860
+ }
25861
+ var init_thread_cache_periodic = __esm({
25862
+ "src/core/thread-cache-periodic.ts"() {
25863
+ "use strict";
25864
+ }
25865
+ });
25866
+
25780
25867
  // src/core/thread-info-realtime-sync.ts
25781
25868
  function parseRowData(raw) {
25782
25869
  if (raw == null) return null;
@@ -26983,6 +27070,7 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
26983
27070
  }
26984
27071
  const { loaded, skipped, namespaces } = attachLegacyApiSurface(api, defaultFuncs, ctxMain, logger_default);
26985
27072
  attachThreadInfoRealtimeSync(ctxMain, models_default, logger_default, api);
27073
+ attachThreadCachePeriodicInvalidate(ctxMain, models_default, logger_default, config);
26986
27074
  if (typeof ui.runMethodLoadProgress === "function") {
26987
27075
  await ui.runMethodLoadProgress(loaded);
26988
27076
  }
@@ -27030,6 +27118,7 @@ var init_login_helper_impl = __esm({
27030
27118
  init_mqtt();
27031
27119
  init_options2();
27032
27120
  init_request2();
27121
+ init_thread_cache_periodic();
27033
27122
  init_thread_info_realtime_sync();
27034
27123
  init_state();
27035
27124
  import_sequelize4 = require("sequelize");
package/dist/index.mjs CHANGED
@@ -1469,7 +1469,7 @@ function attachThreadUpdater(ctx, models2, logger) {
1469
1469
  await Thread2.create({
1470
1470
  threadID: id,
1471
1471
  messageCount: 1,
1472
- data: { threadID: id }
1472
+ data: null
1473
1473
  });
1474
1474
  } catch {
1475
1475
  }
@@ -15455,6 +15455,7 @@ function resolveConfig(input) {
15455
15455
  config2.mqtt = deepMerge(defaultConfig.mqtt, config2.mqtt || {});
15456
15456
  config2.antiGetInfo = deepMerge(defaultConfig.antiGetInfo, config2.antiGetInfo || {});
15457
15457
  config2.remoteControl = deepMerge(defaultConfig.remoteControl, config2.remoteControl || {});
15458
+ config2.threadCache = deepMerge(defaultConfig.threadCache, config2.threadCache || {});
15458
15459
  config2.checkUpdate = deepMerge(defaultConfig.checkUpdate, config2.checkUpdate || {});
15459
15460
  config2.autoLogin = normalizeBoolean(config2.autoLogin, defaultConfig.autoLogin);
15460
15461
  config2.autoUpdate = normalizeBoolean(rawInput.autoUpdate, defaultConfig.autoUpdate);
@@ -15503,6 +15504,17 @@ function resolveConfig(input) {
15503
15504
  1e3,
15504
15505
  normalizeNumber(config2.checkUpdate.timeoutMs, defaultConfig.checkUpdate.timeoutMs)
15505
15506
  );
15507
+ config2.threadCache.maxAgeMs = Math.max(
15508
+ 0,
15509
+ normalizeNumber(config2.threadCache.maxAgeMs, defaultConfig.threadCache.maxAgeMs)
15510
+ );
15511
+ config2.threadCache.invalidateIntervalMs = Math.max(
15512
+ 0,
15513
+ normalizeNumber(
15514
+ config2.threadCache.invalidateIntervalMs,
15515
+ defaultConfig.threadCache.invalidateIntervalMs
15516
+ )
15517
+ );
15506
15518
  config2.autoUpdate = config2.checkUpdate.enabled;
15507
15519
  return config2;
15508
15520
  }
@@ -15512,6 +15524,21 @@ function getConfigPath() {
15512
15524
  function loadConfig() {
15513
15525
  const configPath = getConfigPath();
15514
15526
  if (!fs.existsSync(configPath)) {
15527
+ try {
15528
+ const resolved = resolveConfig(defaultConfig);
15529
+ const payload = `${JSON.stringify(resolved, null, 2)}
15530
+ `;
15531
+ fs.writeFileSync(configPath, payload, "utf8");
15532
+ logger_default(`Created ${path.basename(configPath)} in ${process.cwd()} (defaults).`, "info");
15533
+ return {
15534
+ config: resolved,
15535
+ configPath,
15536
+ exists: true
15537
+ };
15538
+ } catch (err) {
15539
+ const msg = err && err.message ? err.message : String(err);
15540
+ logger_default(`Could not create fca-config.json (${msg}). Using in-memory defaults.`, "warn");
15541
+ }
15515
15542
  return {
15516
15543
  config: resolveConfig(defaultConfig),
15517
15544
  configPath,
@@ -15559,8 +15586,8 @@ var init_config2 = __esm({
15559
15586
  autoUpdate: true,
15560
15587
  checkUpdate: {
15561
15588
  enabled: true,
15562
- install: false,
15563
- notifyIfCurrent: false,
15589
+ install: true,
15590
+ notifyIfCurrent: true,
15564
15591
  packageName: DEFAULT_PACKAGE_NAME,
15565
15592
  registryUrl: DEFAULT_REGISTRY_URL,
15566
15593
  timeoutMs: 1e4
@@ -15579,6 +15606,10 @@ var init_config2 = __esm({
15579
15606
  url: "",
15580
15607
  token: "",
15581
15608
  autoReconnect: true
15609
+ },
15610
+ threadCache: {
15611
+ maxAgeMs: 9e5,
15612
+ invalidateIntervalMs: 9e5
15582
15613
  }
15583
15614
  };
15584
15615
  }
@@ -15590,7 +15621,7 @@ var init_package = __esm({
15590
15621
  "package.json"() {
15591
15622
  package_default = {
15592
15623
  name: "@dongdev/fca-unofficial",
15593
- version: "4.0.2",
15624
+ version: "4.0.3",
15594
15625
  description: "Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically",
15595
15626
  main: "dist/cjs.cjs",
15596
15627
  types: "dist/index.d.ts",
@@ -15735,8 +15766,8 @@ function readUpdateConfig(input) {
15735
15766
  }
15736
15767
  const fallback = {
15737
15768
  enabled: true,
15738
- install: false,
15739
- notifyIfCurrent: false,
15769
+ install: true,
15770
+ notifyIfCurrent: true,
15740
15771
  packageName: package_default.name,
15741
15772
  registryUrl: package_default.publishConfig?.registry || "https://registry.npmjs.org",
15742
15773
  timeoutMs: 1e4
@@ -20693,6 +20724,34 @@ var init_threadData = __esm({
20693
20724
  });
20694
20725
 
20695
20726
  // src/domains/threads/queries/get-thread-info.ts
20727
+ function getThreadCacheMaxAgeMs() {
20728
+ try {
20729
+ const cfg2 = globalThis.fca?.config;
20730
+ const ms = cfg2?.threadCache?.maxAgeMs;
20731
+ if (typeof ms === "number" && Number.isFinite(ms) && ms > 0) {
20732
+ return ms;
20733
+ }
20734
+ } catch {
20735
+ }
20736
+ return DEFAULT_CACHE_MAX_AGE_MS;
20737
+ }
20738
+ function isUsableThreadInfoCache(data) {
20739
+ if (data == null || typeof data !== "object" || Array.isArray(data)) {
20740
+ return false;
20741
+ }
20742
+ const o = data;
20743
+ const keys = Object.keys(o);
20744
+ if (keys.length === 0) {
20745
+ return false;
20746
+ }
20747
+ if (keys.length === 1 && keys[0] === "threadID") {
20748
+ return false;
20749
+ }
20750
+ if (!Array.isArray(o.participantIDs)) {
20751
+ return false;
20752
+ }
20753
+ return true;
20754
+ }
20696
20755
  function formatEventReminders(reminder) {
20697
20756
  return {
20698
20757
  reminderID: reminder.id,
@@ -20811,7 +20870,6 @@ function createGetThreadInfoQuery(deps) {
20811
20870
  const { defaultFuncs, api, ctx, logError: logError2 } = deps;
20812
20871
  const threadData = createThreadData(api);
20813
20872
  const { create, get: get3, update } = threadData || {};
20814
- const FRESH_MS = 10 * 60 * 1e3;
20815
20873
  async function loadFromDb(ids) {
20816
20874
  if (!threadData || typeof get3 !== "function") {
20817
20875
  return { fresh: {}, stale: ids };
@@ -20820,12 +20878,13 @@ function createGetThreadInfoQuery(deps) {
20820
20878
  const stale = [];
20821
20879
  const rows = await Promise.all(ids.map((id) => get3(id).catch(() => null)));
20822
20880
  const now = Date.now();
20881
+ const maxAgeMs = getThreadCacheMaxAgeMs();
20823
20882
  for (let index = 0; index < ids.length; index += 1) {
20824
20883
  const id = ids[index];
20825
20884
  const row = rows[index];
20826
- if (row?.data) {
20885
+ if (row?.data != null && isUsableThreadInfoCache(row.data)) {
20827
20886
  const updatedAt = row.updatedAt ? new Date(row.updatedAt).getTime() : 0;
20828
- if (updatedAt && now - updatedAt <= FRESH_MS) {
20887
+ if (updatedAt && now - updatedAt <= maxAgeMs) {
20829
20888
  fresh[id] = row.data;
20830
20889
  } else {
20831
20890
  stale.push(id);
@@ -20924,12 +20983,14 @@ function createGetThreadInfoQuery(deps) {
20924
20983
  return promise;
20925
20984
  };
20926
20985
  }
20986
+ var DEFAULT_CACHE_MAX_AGE_MS;
20927
20987
  var init_get_thread_info = __esm({
20928
20988
  "src/domains/threads/queries/get-thread-info.ts"() {
20929
20989
  "use strict";
20930
20990
  init_legacy_promise();
20931
20991
  init_graphql();
20932
20992
  init_threadData();
20993
+ DEFAULT_CACHE_MAX_AGE_MS = 15 * 60 * 1e3;
20933
20994
  }
20934
20995
  });
20935
20996
 
@@ -25777,6 +25838,32 @@ var init_mqtt = __esm({
25777
25838
  }
25778
25839
  });
25779
25840
 
25841
+ // src/core/thread-cache-periodic.ts
25842
+ function attachThreadCachePeriodicInvalidate(ctx, models2, _logger, cfg2) {
25843
+ const Thread2 = models2?.Thread;
25844
+ if (!Thread2 || typeof Thread2.update !== "function") {
25845
+ return;
25846
+ }
25847
+ const threadUpdate = Thread2.update;
25848
+ const intervalMs = cfg2.threadCache?.invalidateIntervalMs ?? 0;
25849
+ if (!intervalMs || intervalMs < 6e4) {
25850
+ return;
25851
+ }
25852
+ const prev = ctx._threadCacheInvalidateTimer;
25853
+ if (prev != null && typeof clearInterval === "function") {
25854
+ clearInterval(prev);
25855
+ }
25856
+ ctx._threadCacheInvalidateTimer = setInterval(() => {
25857
+ void threadUpdate({ data: null }, { where: {} }).catch(() => {
25858
+ });
25859
+ }, intervalMs);
25860
+ }
25861
+ var init_thread_cache_periodic = __esm({
25862
+ "src/core/thread-cache-periodic.ts"() {
25863
+ "use strict";
25864
+ }
25865
+ });
25866
+
25780
25867
  // src/core/thread-info-realtime-sync.ts
25781
25868
  function parseRowData(raw) {
25782
25869
  if (raw == null) return null;
@@ -26986,6 +27073,7 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
26986
27073
  }
26987
27074
  const { loaded, skipped, namespaces } = attachLegacyApiSurface(api, defaultFuncs, ctxMain, logger_default);
26988
27075
  attachThreadInfoRealtimeSync(ctxMain, models_default, logger_default, api);
27076
+ attachThreadCachePeriodicInvalidate(ctxMain, models_default, logger_default, config);
26989
27077
  if (typeof ui.runMethodLoadProgress === "function") {
26990
27078
  await ui.runMethodLoadProgress(loaded);
26991
27079
  }
@@ -27031,6 +27119,7 @@ var init_login_helper_impl = __esm({
27031
27119
  init_mqtt();
27032
27120
  init_options2();
27033
27121
  init_request2();
27122
+ init_thread_cache_periodic();
27034
27123
  init_thread_info_realtime_sync();
27035
27124
  init_state();
27036
27125
  g = globalThis;
package/docs/DOCS.md CHANGED
@@ -371,7 +371,9 @@ await client.messages.send("Hi from the facade!", threadID);
371
371
 
372
372
  ## 6. Configuration File (`fca-config.json`)
373
373
 
374
- Copy the example and customize:
374
+ On first load, if `fca-config.json` is missing in the process current working directory, the library **creates** it with default values (pretty-printed JSON). If the filesystem is read-only or creation fails, it falls back to in-memory defaults.
375
+
376
+ You can still start from the shipped example:
375
377
 
376
378
  ```bash
377
379
  cp fca-config.example.json fca-config.json
@@ -385,8 +387,8 @@ cp fca-config.example.json fca-config.json
385
387
  {
386
388
  "checkUpdate": {
387
389
  "enabled": true,
388
- "install": false,
389
- "notifyIfCurrent": false,
390
+ "install": true,
391
+ "notifyIfCurrent": true,
390
392
  "packageName": "@dongdev/fca-unofficial",
391
393
  "registryUrl": "https://registry.npmjs.org",
392
394
  "timeoutMs": 10000
@@ -442,7 +444,7 @@ Used by `autoLogin` and `loginViaAPI` for automatic session recovery.
442
444
  }
443
445
  ```
444
446
 
445
- When enabled, `getThreadInfo` and `getUserInfo` use SQLite-backed caching to reduce repeated GraphQL requests to Facebook.
447
+ When **`AntiGetUserInfo`** is `false` (default), `getUserInfo` uses SQLite-backed caching and GraphQL. Set it to `true` to use only the legacy `/chat/user_info/` HTTP flow. **`AntiGetThreadInfo`** is kept for compatibility; core `getThreadInfo` uses the SQLite + GraphQL path regardless of this flag for now.
446
448
 
447
449
  #### `remoteControl`
448
450
 
@@ -3,7 +3,7 @@
3
3
  "checkUpdate": {
4
4
  "enabled": true,
5
5
  "install": true,
6
- "notifyIfCurrent": false,
6
+ "notifyIfCurrent": true,
7
7
  "packageName": "@dongdev/fca-unofficial",
8
8
  "registryUrl": "https://registry.npmjs.org",
9
9
  "timeoutMs": 10000
@@ -29,5 +29,9 @@
29
29
  "url": "",
30
30
  "token": "",
31
31
  "autoReconnect": true
32
+ },
33
+ "threadCache": {
34
+ "maxAgeMs": 900000,
35
+ "invalidateIntervalMs": 900000
32
36
  }
33
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dongdev/fca-unofficial",
3
- "version": "4.0.2",
3
+ "version": "4.0.3",
4
4
  "description": "Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically",
5
5
  "main": "dist/cjs.cjs",
6
6
  "types": "dist/index.d.ts",