@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 +3 -1
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +98 -9
- package/dist/index.mjs +98 -9
- package/docs/DOCS.md +6 -4
- package/fca-config.example.json +5 -1
- package/package.json +1 -1
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
|
-
|
|
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:
|
|
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:
|
|
15559
|
-
notifyIfCurrent:
|
|
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.
|
|
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:
|
|
15733
|
-
notifyIfCurrent:
|
|
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 <=
|
|
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:
|
|
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:
|
|
15563
|
-
notifyIfCurrent:
|
|
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.
|
|
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:
|
|
15739
|
-
notifyIfCurrent:
|
|
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 <=
|
|
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
|
-
|
|
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":
|
|
389
|
-
"notifyIfCurrent":
|
|
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
|
|
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
|
|
package/fca-config.example.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"checkUpdate": {
|
|
4
4
|
"enabled": true,
|
|
5
5
|
"install": true,
|
|
6
|
-
"notifyIfCurrent":
|
|
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