@dongdev/fca-unofficial 4.0.1 → 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 +101 -79
- package/dist/index.mjs +101 -79
- package/docs/DOCS.md +6 -4
- package/fca-config.example.json +6 -2
- package/package.json +1 -2
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
|
@@ -65,8 +65,7 @@ function makeStyles(theme) {
|
|
|
65
65
|
info: (v) => import_picocolors.default.cyan(v),
|
|
66
66
|
warn: (v) => import_picocolors.default.yellow(v),
|
|
67
67
|
error: (v) => import_picocolors.default.red(v),
|
|
68
|
-
sys: (v) => import_picocolors.default.blue(v)
|
|
69
|
-
banner: (v) => import_picocolors.default.white(v)
|
|
68
|
+
sys: (v) => import_picocolors.default.blue(v)
|
|
70
69
|
};
|
|
71
70
|
}
|
|
72
71
|
return {
|
|
@@ -75,8 +74,7 @@ function makeStyles(theme) {
|
|
|
75
74
|
info: (v) => import_picocolors.default.cyan(v),
|
|
76
75
|
warn: (v) => import_picocolors.default.yellow(v),
|
|
77
76
|
error: (v) => import_picocolors.default.red(v),
|
|
78
|
-
sys: (v) => import_picocolors.default.blue(v)
|
|
79
|
-
banner: (v) => import_picocolors.default.cyan(v)
|
|
77
|
+
sys: (v) => import_picocolors.default.blue(v)
|
|
80
78
|
};
|
|
81
79
|
}
|
|
82
80
|
function parseLabel(message, fallback) {
|
|
@@ -109,22 +107,7 @@ function formatSuccessBody(body, grad, fallbackPaint) {
|
|
|
109
107
|
}
|
|
110
108
|
return fallbackPaint(body);
|
|
111
109
|
}
|
|
112
|
-
function donixAsciiBlock() {
|
|
113
|
-
return [
|
|
114
|
-
"____ ____ ____ ____ ____",
|
|
115
|
-
"||D ||||O ||||N ||||I ||||X ||",
|
|
116
|
-
"||__||||__||||__||||__||||__||",
|
|
117
|
-
"|/__\\||/__\\||/__\\||/__\\||/__\\|"
|
|
118
|
-
].join("\n");
|
|
119
|
-
}
|
|
120
110
|
async function ensureUiLibs() {
|
|
121
|
-
if (!boxenLib) {
|
|
122
|
-
try {
|
|
123
|
-
const boxenMod = await import("boxen");
|
|
124
|
-
boxenLib = boxenMod.default ?? boxenMod;
|
|
125
|
-
} catch {
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
111
|
if (!oraFactory) {
|
|
129
112
|
try {
|
|
130
113
|
const oraMod = await import("ora");
|
|
@@ -141,51 +124,6 @@ async function ensureUiLibs() {
|
|
|
141
124
|
}
|
|
142
125
|
}
|
|
143
126
|
}
|
|
144
|
-
function printBootBanner(styles) {
|
|
145
|
-
if (didPrintBootBanner) return;
|
|
146
|
-
didPrintBootBanner = true;
|
|
147
|
-
const version = process.env.npm_package_version || "4.0.1";
|
|
148
|
-
const theme = getTheme();
|
|
149
|
-
const grad = theme === "cyberpunk" ? loadGradientFns() : null;
|
|
150
|
-
if (theme === "cyberpunk" && grad && boxenLib) {
|
|
151
|
-
const asciiStyled = grad.cyberpunk(donixAsciiBlock());
|
|
152
|
-
const titleLine = `${import_picocolors.default.bold(grad.coolStatus("FCA-UNOFFICIAL"))} ${import_picocolors.default.dim(`v${version}`)}`;
|
|
153
|
-
const body2 = `${asciiStyled}
|
|
154
|
-
${titleLine}
|
|
155
|
-
${styles.text("Author:")} ${grad.coolStatus("DongDev (Donix-VN)")}
|
|
156
|
-
${styles.text("Status:")} ${import_picocolors.default.green("Ready to Connect")}`;
|
|
157
|
-
writeStdout(
|
|
158
|
-
boxenLib(body2, {
|
|
159
|
-
padding: 1,
|
|
160
|
-
margin: 0,
|
|
161
|
-
borderStyle: "double",
|
|
162
|
-
borderColor: "cyan"
|
|
163
|
-
})
|
|
164
|
-
);
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
const art = [
|
|
168
|
-
"\u2554\u2566\u2557\u2554\u2550\u2557\u2554\u2557\u2554\u2566\u2550\u2557\u2566 \u2566",
|
|
169
|
-
" \u2551\u2551\u2551 \u2551\u2551\u2551\u2551\u2560\u2566\u255D\u255A\u2566\u255D",
|
|
170
|
-
"\u2550\u2569\u255D\u255A\u2550\u255D\u255D\u255A\u255D\u2569\u255A\u2550 \u2569 DONIX"
|
|
171
|
-
].join("\n");
|
|
172
|
-
const body = `${import_picocolors.default.bold(styles.info("FCA-UNOFFICIAL"))} ${import_picocolors.default.dim(`v${version}`)}
|
|
173
|
-
${styles.text("Author:")} ${styles.info("DongDev (Donix-VN)")}
|
|
174
|
-
${styles.text("Status:")} ${import_picocolors.default.green("Ready to Connect")}
|
|
175
|
-
${styles.banner(art)}`;
|
|
176
|
-
if (boxenLib) {
|
|
177
|
-
writeStdout(
|
|
178
|
-
boxenLib(body, {
|
|
179
|
-
padding: 1,
|
|
180
|
-
margin: 0,
|
|
181
|
-
borderStyle: "round",
|
|
182
|
-
borderColor: "cyan"
|
|
183
|
-
})
|
|
184
|
-
);
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
writeStdout(styles.banner(body));
|
|
188
|
-
}
|
|
189
127
|
function logLine(text, type) {
|
|
190
128
|
const level = String(type || "info").toLowerCase();
|
|
191
129
|
const message = String(text ?? "");
|
|
@@ -222,14 +160,12 @@ function logLine(text, type) {
|
|
|
222
160
|
const bodyOut = grad ? grad.coolStatus(parts.body) : styles.info(parts.body);
|
|
223
161
|
writeStdout(`${ts} ${labelOut} : ${bodyOut}`);
|
|
224
162
|
}
|
|
225
|
-
var import_picocolors, import_gradient_string,
|
|
163
|
+
var import_picocolors, import_gradient_string, oraFactory, progressCtor, progressPreset, gradientFns, baseLogger, logger_default;
|
|
226
164
|
var init_logger = __esm({
|
|
227
165
|
"src/func/logger.ts"() {
|
|
228
166
|
"use strict";
|
|
229
167
|
import_picocolors = __toESM(require("picocolors"));
|
|
230
168
|
import_gradient_string = __toESM(require("gradient-string"));
|
|
231
|
-
didPrintBootBanner = false;
|
|
232
|
-
boxenLib = null;
|
|
233
169
|
oraFactory = null;
|
|
234
170
|
progressCtor = null;
|
|
235
171
|
progressPreset = null;
|
|
@@ -240,8 +176,6 @@ var init_logger = __esm({
|
|
|
240
176
|
baseLogger.warn = (text) => baseLogger(text, "warn");
|
|
241
177
|
baseLogger.error = (text) => baseLogger(text, "error");
|
|
242
178
|
baseLogger.showBanner = async () => {
|
|
243
|
-
await ensureUiLibs();
|
|
244
|
-
printBootBanner(makeStyles(getTheme()));
|
|
245
179
|
};
|
|
246
180
|
baseLogger.startSpinner = async (text) => {
|
|
247
181
|
await ensureUiLibs();
|
|
@@ -1530,7 +1464,7 @@ function attachThreadUpdater(ctx, models2, logger) {
|
|
|
1530
1464
|
await Thread2.create({
|
|
1531
1465
|
threadID: id,
|
|
1532
1466
|
messageCount: 1,
|
|
1533
|
-
data:
|
|
1467
|
+
data: null
|
|
1534
1468
|
});
|
|
1535
1469
|
} catch {
|
|
1536
1470
|
}
|
|
@@ -15515,6 +15449,7 @@ function resolveConfig(input) {
|
|
|
15515
15449
|
config2.mqtt = deepMerge(defaultConfig.mqtt, config2.mqtt || {});
|
|
15516
15450
|
config2.antiGetInfo = deepMerge(defaultConfig.antiGetInfo, config2.antiGetInfo || {});
|
|
15517
15451
|
config2.remoteControl = deepMerge(defaultConfig.remoteControl, config2.remoteControl || {});
|
|
15452
|
+
config2.threadCache = deepMerge(defaultConfig.threadCache, config2.threadCache || {});
|
|
15518
15453
|
config2.checkUpdate = deepMerge(defaultConfig.checkUpdate, config2.checkUpdate || {});
|
|
15519
15454
|
config2.autoLogin = normalizeBoolean(config2.autoLogin, defaultConfig.autoLogin);
|
|
15520
15455
|
config2.autoUpdate = normalizeBoolean(rawInput.autoUpdate, defaultConfig.autoUpdate);
|
|
@@ -15563,6 +15498,17 @@ function resolveConfig(input) {
|
|
|
15563
15498
|
1e3,
|
|
15564
15499
|
normalizeNumber(config2.checkUpdate.timeoutMs, defaultConfig.checkUpdate.timeoutMs)
|
|
15565
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
|
+
);
|
|
15566
15512
|
config2.autoUpdate = config2.checkUpdate.enabled;
|
|
15567
15513
|
return config2;
|
|
15568
15514
|
}
|
|
@@ -15572,6 +15518,21 @@ function getConfigPath() {
|
|
|
15572
15518
|
function loadConfig() {
|
|
15573
15519
|
const configPath = getConfigPath();
|
|
15574
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
|
+
}
|
|
15575
15536
|
return {
|
|
15576
15537
|
config: resolveConfig(defaultConfig),
|
|
15577
15538
|
configPath,
|
|
@@ -15621,8 +15582,8 @@ var init_config2 = __esm({
|
|
|
15621
15582
|
autoUpdate: true,
|
|
15622
15583
|
checkUpdate: {
|
|
15623
15584
|
enabled: true,
|
|
15624
|
-
install:
|
|
15625
|
-
notifyIfCurrent:
|
|
15585
|
+
install: true,
|
|
15586
|
+
notifyIfCurrent: true,
|
|
15626
15587
|
packageName: DEFAULT_PACKAGE_NAME,
|
|
15627
15588
|
registryUrl: DEFAULT_REGISTRY_URL,
|
|
15628
15589
|
timeoutMs: 1e4
|
|
@@ -15641,6 +15602,10 @@ var init_config2 = __esm({
|
|
|
15641
15602
|
url: "",
|
|
15642
15603
|
token: "",
|
|
15643
15604
|
autoReconnect: true
|
|
15605
|
+
},
|
|
15606
|
+
threadCache: {
|
|
15607
|
+
maxAgeMs: 9e5,
|
|
15608
|
+
invalidateIntervalMs: 9e5
|
|
15644
15609
|
}
|
|
15645
15610
|
};
|
|
15646
15611
|
}
|
|
@@ -15652,7 +15617,7 @@ var init_package = __esm({
|
|
|
15652
15617
|
"package.json"() {
|
|
15653
15618
|
package_default = {
|
|
15654
15619
|
name: "@dongdev/fca-unofficial",
|
|
15655
|
-
version: "4.0.
|
|
15620
|
+
version: "4.0.3",
|
|
15656
15621
|
description: "Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically",
|
|
15657
15622
|
main: "dist/cjs.cjs",
|
|
15658
15623
|
types: "dist/index.d.ts",
|
|
@@ -15721,7 +15686,6 @@ var init_package = __esm({
|
|
|
15721
15686
|
axios: "^1.13.5",
|
|
15722
15687
|
"axios-cookiejar-support": "^5.0.5",
|
|
15723
15688
|
bluebird: "^3.7.2",
|
|
15724
|
-
boxen: "^8.0.1",
|
|
15725
15689
|
cheerio: "^1.0.0-rc.10",
|
|
15726
15690
|
"cli-progress": "^3.12.0",
|
|
15727
15691
|
duplexify: "^4.1.3",
|
|
@@ -15796,8 +15760,8 @@ function readUpdateConfig(input) {
|
|
|
15796
15760
|
}
|
|
15797
15761
|
const fallback = {
|
|
15798
15762
|
enabled: true,
|
|
15799
|
-
install:
|
|
15800
|
-
notifyIfCurrent:
|
|
15763
|
+
install: true,
|
|
15764
|
+
notifyIfCurrent: true,
|
|
15801
15765
|
packageName: package_default.name,
|
|
15802
15766
|
registryUrl: package_default.publishConfig?.registry || "https://registry.npmjs.org",
|
|
15803
15767
|
timeoutMs: 1e4
|
|
@@ -20759,6 +20723,34 @@ var init_threadData = __esm({
|
|
|
20759
20723
|
});
|
|
20760
20724
|
|
|
20761
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
|
+
}
|
|
20762
20754
|
function formatEventReminders(reminder) {
|
|
20763
20755
|
return {
|
|
20764
20756
|
reminderID: reminder.id,
|
|
@@ -20877,7 +20869,6 @@ function createGetThreadInfoQuery(deps) {
|
|
|
20877
20869
|
const { defaultFuncs, api, ctx, logError: logError2 } = deps;
|
|
20878
20870
|
const threadData = createThreadData(api);
|
|
20879
20871
|
const { create, get: get3, update } = threadData || {};
|
|
20880
|
-
const FRESH_MS = 10 * 60 * 1e3;
|
|
20881
20872
|
async function loadFromDb(ids) {
|
|
20882
20873
|
if (!threadData || typeof get3 !== "function") {
|
|
20883
20874
|
return { fresh: {}, stale: ids };
|
|
@@ -20886,12 +20877,13 @@ function createGetThreadInfoQuery(deps) {
|
|
|
20886
20877
|
const stale = [];
|
|
20887
20878
|
const rows = await Promise.all(ids.map((id) => get3(id).catch(() => null)));
|
|
20888
20879
|
const now = Date.now();
|
|
20880
|
+
const maxAgeMs = getThreadCacheMaxAgeMs();
|
|
20889
20881
|
for (let index = 0; index < ids.length; index += 1) {
|
|
20890
20882
|
const id = ids[index];
|
|
20891
20883
|
const row = rows[index];
|
|
20892
|
-
if (row?.data) {
|
|
20884
|
+
if (row?.data != null && isUsableThreadInfoCache(row.data)) {
|
|
20893
20885
|
const updatedAt = row.updatedAt ? new Date(row.updatedAt).getTime() : 0;
|
|
20894
|
-
if (updatedAt && now - updatedAt <=
|
|
20886
|
+
if (updatedAt && now - updatedAt <= maxAgeMs) {
|
|
20895
20887
|
fresh[id] = row.data;
|
|
20896
20888
|
} else {
|
|
20897
20889
|
stale.push(id);
|
|
@@ -20990,12 +20982,14 @@ function createGetThreadInfoQuery(deps) {
|
|
|
20990
20982
|
return promise;
|
|
20991
20983
|
};
|
|
20992
20984
|
}
|
|
20985
|
+
var DEFAULT_CACHE_MAX_AGE_MS;
|
|
20993
20986
|
var init_get_thread_info = __esm({
|
|
20994
20987
|
"src/domains/threads/queries/get-thread-info.ts"() {
|
|
20995
20988
|
"use strict";
|
|
20996
20989
|
init_legacy_promise();
|
|
20997
20990
|
init_graphql();
|
|
20998
20991
|
init_threadData();
|
|
20992
|
+
DEFAULT_CACHE_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
20999
20993
|
}
|
|
21000
20994
|
});
|
|
21001
20995
|
|
|
@@ -25844,6 +25838,32 @@ var init_mqtt = __esm({
|
|
|
25844
25838
|
}
|
|
25845
25839
|
});
|
|
25846
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
|
+
|
|
25847
25867
|
// src/core/thread-info-realtime-sync.ts
|
|
25848
25868
|
function parseRowData(raw) {
|
|
25849
25869
|
if (raw == null) return null;
|
|
@@ -27050,6 +27070,7 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
|
|
|
27050
27070
|
}
|
|
27051
27071
|
const { loaded, skipped, namespaces } = attachLegacyApiSurface(api, defaultFuncs, ctxMain, logger_default);
|
|
27052
27072
|
attachThreadInfoRealtimeSync(ctxMain, models_default, logger_default, api);
|
|
27073
|
+
attachThreadCachePeriodicInvalidate(ctxMain, models_default, logger_default, config);
|
|
27053
27074
|
if (typeof ui.runMethodLoadProgress === "function") {
|
|
27054
27075
|
await ui.runMethodLoadProgress(loaded);
|
|
27055
27076
|
}
|
|
@@ -27097,6 +27118,7 @@ var init_login_helper_impl = __esm({
|
|
|
27097
27118
|
init_mqtt();
|
|
27098
27119
|
init_options2();
|
|
27099
27120
|
init_request2();
|
|
27121
|
+
init_thread_cache_periodic();
|
|
27100
27122
|
init_thread_info_realtime_sync();
|
|
27101
27123
|
init_state();
|
|
27102
27124
|
import_sequelize4 = require("sequelize");
|
package/dist/index.mjs
CHANGED
|
@@ -72,8 +72,7 @@ function makeStyles(theme) {
|
|
|
72
72
|
info: (v) => pc.cyan(v),
|
|
73
73
|
warn: (v) => pc.yellow(v),
|
|
74
74
|
error: (v) => pc.red(v),
|
|
75
|
-
sys: (v) => pc.blue(v)
|
|
76
|
-
banner: (v) => pc.white(v)
|
|
75
|
+
sys: (v) => pc.blue(v)
|
|
77
76
|
};
|
|
78
77
|
}
|
|
79
78
|
return {
|
|
@@ -82,8 +81,7 @@ function makeStyles(theme) {
|
|
|
82
81
|
info: (v) => pc.cyan(v),
|
|
83
82
|
warn: (v) => pc.yellow(v),
|
|
84
83
|
error: (v) => pc.red(v),
|
|
85
|
-
sys: (v) => pc.blue(v)
|
|
86
|
-
banner: (v) => pc.cyan(v)
|
|
84
|
+
sys: (v) => pc.blue(v)
|
|
87
85
|
};
|
|
88
86
|
}
|
|
89
87
|
function parseLabel(message, fallback) {
|
|
@@ -116,22 +114,7 @@ function formatSuccessBody(body, grad, fallbackPaint) {
|
|
|
116
114
|
}
|
|
117
115
|
return fallbackPaint(body);
|
|
118
116
|
}
|
|
119
|
-
function donixAsciiBlock() {
|
|
120
|
-
return [
|
|
121
|
-
"____ ____ ____ ____ ____",
|
|
122
|
-
"||D ||||O ||||N ||||I ||||X ||",
|
|
123
|
-
"||__||||__||||__||||__||||__||",
|
|
124
|
-
"|/__\\||/__\\||/__\\||/__\\||/__\\|"
|
|
125
|
-
].join("\n");
|
|
126
|
-
}
|
|
127
117
|
async function ensureUiLibs() {
|
|
128
|
-
if (!boxenLib) {
|
|
129
|
-
try {
|
|
130
|
-
const boxenMod = await import("boxen");
|
|
131
|
-
boxenLib = boxenMod.default ?? boxenMod;
|
|
132
|
-
} catch {
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
118
|
if (!oraFactory) {
|
|
136
119
|
try {
|
|
137
120
|
const oraMod = await import("ora");
|
|
@@ -148,51 +131,6 @@ async function ensureUiLibs() {
|
|
|
148
131
|
}
|
|
149
132
|
}
|
|
150
133
|
}
|
|
151
|
-
function printBootBanner(styles) {
|
|
152
|
-
if (didPrintBootBanner) return;
|
|
153
|
-
didPrintBootBanner = true;
|
|
154
|
-
const version = process.env.npm_package_version || "4.0.1";
|
|
155
|
-
const theme = getTheme();
|
|
156
|
-
const grad = theme === "cyberpunk" ? loadGradientFns() : null;
|
|
157
|
-
if (theme === "cyberpunk" && grad && boxenLib) {
|
|
158
|
-
const asciiStyled = grad.cyberpunk(donixAsciiBlock());
|
|
159
|
-
const titleLine = `${pc.bold(grad.coolStatus("FCA-UNOFFICIAL"))} ${pc.dim(`v${version}`)}`;
|
|
160
|
-
const body2 = `${asciiStyled}
|
|
161
|
-
${titleLine}
|
|
162
|
-
${styles.text("Author:")} ${grad.coolStatus("DongDev (Donix-VN)")}
|
|
163
|
-
${styles.text("Status:")} ${pc.green("Ready to Connect")}`;
|
|
164
|
-
writeStdout(
|
|
165
|
-
boxenLib(body2, {
|
|
166
|
-
padding: 1,
|
|
167
|
-
margin: 0,
|
|
168
|
-
borderStyle: "double",
|
|
169
|
-
borderColor: "cyan"
|
|
170
|
-
})
|
|
171
|
-
);
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const art = [
|
|
175
|
-
"\u2554\u2566\u2557\u2554\u2550\u2557\u2554\u2557\u2554\u2566\u2550\u2557\u2566 \u2566",
|
|
176
|
-
" \u2551\u2551\u2551 \u2551\u2551\u2551\u2551\u2560\u2566\u255D\u255A\u2566\u255D",
|
|
177
|
-
"\u2550\u2569\u255D\u255A\u2550\u255D\u255D\u255A\u255D\u2569\u255A\u2550 \u2569 DONIX"
|
|
178
|
-
].join("\n");
|
|
179
|
-
const body = `${pc.bold(styles.info("FCA-UNOFFICIAL"))} ${pc.dim(`v${version}`)}
|
|
180
|
-
${styles.text("Author:")} ${styles.info("DongDev (Donix-VN)")}
|
|
181
|
-
${styles.text("Status:")} ${pc.green("Ready to Connect")}
|
|
182
|
-
${styles.banner(art)}`;
|
|
183
|
-
if (boxenLib) {
|
|
184
|
-
writeStdout(
|
|
185
|
-
boxenLib(body, {
|
|
186
|
-
padding: 1,
|
|
187
|
-
margin: 0,
|
|
188
|
-
borderStyle: "round",
|
|
189
|
-
borderColor: "cyan"
|
|
190
|
-
})
|
|
191
|
-
);
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
writeStdout(styles.banner(body));
|
|
195
|
-
}
|
|
196
134
|
function logLine(text, type) {
|
|
197
135
|
const level = String(type || "info").toLowerCase();
|
|
198
136
|
const message = String(text ?? "");
|
|
@@ -229,12 +167,10 @@ function logLine(text, type) {
|
|
|
229
167
|
const bodyOut = grad ? grad.coolStatus(parts.body) : styles.info(parts.body);
|
|
230
168
|
writeStdout(`${ts} ${labelOut} : ${bodyOut}`);
|
|
231
169
|
}
|
|
232
|
-
var
|
|
170
|
+
var oraFactory, progressCtor, progressPreset, gradientFns, baseLogger, logger_default;
|
|
233
171
|
var init_logger = __esm({
|
|
234
172
|
"src/func/logger.ts"() {
|
|
235
173
|
"use strict";
|
|
236
|
-
didPrintBootBanner = false;
|
|
237
|
-
boxenLib = null;
|
|
238
174
|
oraFactory = null;
|
|
239
175
|
progressCtor = null;
|
|
240
176
|
progressPreset = null;
|
|
@@ -245,8 +181,6 @@ var init_logger = __esm({
|
|
|
245
181
|
baseLogger.warn = (text) => baseLogger(text, "warn");
|
|
246
182
|
baseLogger.error = (text) => baseLogger(text, "error");
|
|
247
183
|
baseLogger.showBanner = async () => {
|
|
248
|
-
await ensureUiLibs();
|
|
249
|
-
printBootBanner(makeStyles(getTheme()));
|
|
250
184
|
};
|
|
251
185
|
baseLogger.startSpinner = async (text) => {
|
|
252
186
|
await ensureUiLibs();
|
|
@@ -1535,7 +1469,7 @@ function attachThreadUpdater(ctx, models2, logger) {
|
|
|
1535
1469
|
await Thread2.create({
|
|
1536
1470
|
threadID: id,
|
|
1537
1471
|
messageCount: 1,
|
|
1538
|
-
data:
|
|
1472
|
+
data: null
|
|
1539
1473
|
});
|
|
1540
1474
|
} catch {
|
|
1541
1475
|
}
|
|
@@ -15521,6 +15455,7 @@ function resolveConfig(input) {
|
|
|
15521
15455
|
config2.mqtt = deepMerge(defaultConfig.mqtt, config2.mqtt || {});
|
|
15522
15456
|
config2.antiGetInfo = deepMerge(defaultConfig.antiGetInfo, config2.antiGetInfo || {});
|
|
15523
15457
|
config2.remoteControl = deepMerge(defaultConfig.remoteControl, config2.remoteControl || {});
|
|
15458
|
+
config2.threadCache = deepMerge(defaultConfig.threadCache, config2.threadCache || {});
|
|
15524
15459
|
config2.checkUpdate = deepMerge(defaultConfig.checkUpdate, config2.checkUpdate || {});
|
|
15525
15460
|
config2.autoLogin = normalizeBoolean(config2.autoLogin, defaultConfig.autoLogin);
|
|
15526
15461
|
config2.autoUpdate = normalizeBoolean(rawInput.autoUpdate, defaultConfig.autoUpdate);
|
|
@@ -15569,6 +15504,17 @@ function resolveConfig(input) {
|
|
|
15569
15504
|
1e3,
|
|
15570
15505
|
normalizeNumber(config2.checkUpdate.timeoutMs, defaultConfig.checkUpdate.timeoutMs)
|
|
15571
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
|
+
);
|
|
15572
15518
|
config2.autoUpdate = config2.checkUpdate.enabled;
|
|
15573
15519
|
return config2;
|
|
15574
15520
|
}
|
|
@@ -15578,6 +15524,21 @@ function getConfigPath() {
|
|
|
15578
15524
|
function loadConfig() {
|
|
15579
15525
|
const configPath = getConfigPath();
|
|
15580
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
|
+
}
|
|
15581
15542
|
return {
|
|
15582
15543
|
config: resolveConfig(defaultConfig),
|
|
15583
15544
|
configPath,
|
|
@@ -15625,8 +15586,8 @@ var init_config2 = __esm({
|
|
|
15625
15586
|
autoUpdate: true,
|
|
15626
15587
|
checkUpdate: {
|
|
15627
15588
|
enabled: true,
|
|
15628
|
-
install:
|
|
15629
|
-
notifyIfCurrent:
|
|
15589
|
+
install: true,
|
|
15590
|
+
notifyIfCurrent: true,
|
|
15630
15591
|
packageName: DEFAULT_PACKAGE_NAME,
|
|
15631
15592
|
registryUrl: DEFAULT_REGISTRY_URL,
|
|
15632
15593
|
timeoutMs: 1e4
|
|
@@ -15645,6 +15606,10 @@ var init_config2 = __esm({
|
|
|
15645
15606
|
url: "",
|
|
15646
15607
|
token: "",
|
|
15647
15608
|
autoReconnect: true
|
|
15609
|
+
},
|
|
15610
|
+
threadCache: {
|
|
15611
|
+
maxAgeMs: 9e5,
|
|
15612
|
+
invalidateIntervalMs: 9e5
|
|
15648
15613
|
}
|
|
15649
15614
|
};
|
|
15650
15615
|
}
|
|
@@ -15656,7 +15621,7 @@ var init_package = __esm({
|
|
|
15656
15621
|
"package.json"() {
|
|
15657
15622
|
package_default = {
|
|
15658
15623
|
name: "@dongdev/fca-unofficial",
|
|
15659
|
-
version: "4.0.
|
|
15624
|
+
version: "4.0.3",
|
|
15660
15625
|
description: "Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically",
|
|
15661
15626
|
main: "dist/cjs.cjs",
|
|
15662
15627
|
types: "dist/index.d.ts",
|
|
@@ -15725,7 +15690,6 @@ var init_package = __esm({
|
|
|
15725
15690
|
axios: "^1.13.5",
|
|
15726
15691
|
"axios-cookiejar-support": "^5.0.5",
|
|
15727
15692
|
bluebird: "^3.7.2",
|
|
15728
|
-
boxen: "^8.0.1",
|
|
15729
15693
|
cheerio: "^1.0.0-rc.10",
|
|
15730
15694
|
"cli-progress": "^3.12.0",
|
|
15731
15695
|
duplexify: "^4.1.3",
|
|
@@ -15802,8 +15766,8 @@ function readUpdateConfig(input) {
|
|
|
15802
15766
|
}
|
|
15803
15767
|
const fallback = {
|
|
15804
15768
|
enabled: true,
|
|
15805
|
-
install:
|
|
15806
|
-
notifyIfCurrent:
|
|
15769
|
+
install: true,
|
|
15770
|
+
notifyIfCurrent: true,
|
|
15807
15771
|
packageName: package_default.name,
|
|
15808
15772
|
registryUrl: package_default.publishConfig?.registry || "https://registry.npmjs.org",
|
|
15809
15773
|
timeoutMs: 1e4
|
|
@@ -20760,6 +20724,34 @@ var init_threadData = __esm({
|
|
|
20760
20724
|
});
|
|
20761
20725
|
|
|
20762
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
|
+
}
|
|
20763
20755
|
function formatEventReminders(reminder) {
|
|
20764
20756
|
return {
|
|
20765
20757
|
reminderID: reminder.id,
|
|
@@ -20878,7 +20870,6 @@ function createGetThreadInfoQuery(deps) {
|
|
|
20878
20870
|
const { defaultFuncs, api, ctx, logError: logError2 } = deps;
|
|
20879
20871
|
const threadData = createThreadData(api);
|
|
20880
20872
|
const { create, get: get3, update } = threadData || {};
|
|
20881
|
-
const FRESH_MS = 10 * 60 * 1e3;
|
|
20882
20873
|
async function loadFromDb(ids) {
|
|
20883
20874
|
if (!threadData || typeof get3 !== "function") {
|
|
20884
20875
|
return { fresh: {}, stale: ids };
|
|
@@ -20887,12 +20878,13 @@ function createGetThreadInfoQuery(deps) {
|
|
|
20887
20878
|
const stale = [];
|
|
20888
20879
|
const rows = await Promise.all(ids.map((id) => get3(id).catch(() => null)));
|
|
20889
20880
|
const now = Date.now();
|
|
20881
|
+
const maxAgeMs = getThreadCacheMaxAgeMs();
|
|
20890
20882
|
for (let index = 0; index < ids.length; index += 1) {
|
|
20891
20883
|
const id = ids[index];
|
|
20892
20884
|
const row = rows[index];
|
|
20893
|
-
if (row?.data) {
|
|
20885
|
+
if (row?.data != null && isUsableThreadInfoCache(row.data)) {
|
|
20894
20886
|
const updatedAt = row.updatedAt ? new Date(row.updatedAt).getTime() : 0;
|
|
20895
|
-
if (updatedAt && now - updatedAt <=
|
|
20887
|
+
if (updatedAt && now - updatedAt <= maxAgeMs) {
|
|
20896
20888
|
fresh[id] = row.data;
|
|
20897
20889
|
} else {
|
|
20898
20890
|
stale.push(id);
|
|
@@ -20991,12 +20983,14 @@ function createGetThreadInfoQuery(deps) {
|
|
|
20991
20983
|
return promise;
|
|
20992
20984
|
};
|
|
20993
20985
|
}
|
|
20986
|
+
var DEFAULT_CACHE_MAX_AGE_MS;
|
|
20994
20987
|
var init_get_thread_info = __esm({
|
|
20995
20988
|
"src/domains/threads/queries/get-thread-info.ts"() {
|
|
20996
20989
|
"use strict";
|
|
20997
20990
|
init_legacy_promise();
|
|
20998
20991
|
init_graphql();
|
|
20999
20992
|
init_threadData();
|
|
20993
|
+
DEFAULT_CACHE_MAX_AGE_MS = 15 * 60 * 1e3;
|
|
21000
20994
|
}
|
|
21001
20995
|
});
|
|
21002
20996
|
|
|
@@ -25844,6 +25838,32 @@ var init_mqtt = __esm({
|
|
|
25844
25838
|
}
|
|
25845
25839
|
});
|
|
25846
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
|
+
|
|
25847
25867
|
// src/core/thread-info-realtime-sync.ts
|
|
25848
25868
|
function parseRowData(raw) {
|
|
25849
25869
|
if (raw == null) return null;
|
|
@@ -27053,6 +27073,7 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
|
|
|
27053
27073
|
}
|
|
27054
27074
|
const { loaded, skipped, namespaces } = attachLegacyApiSurface(api, defaultFuncs, ctxMain, logger_default);
|
|
27055
27075
|
attachThreadInfoRealtimeSync(ctxMain, models_default, logger_default, api);
|
|
27076
|
+
attachThreadCachePeriodicInvalidate(ctxMain, models_default, logger_default, config);
|
|
27056
27077
|
if (typeof ui.runMethodLoadProgress === "function") {
|
|
27057
27078
|
await ui.runMethodLoadProgress(loaded);
|
|
27058
27079
|
}
|
|
@@ -27098,6 +27119,7 @@ var init_login_helper_impl = __esm({
|
|
|
27098
27119
|
init_mqtt();
|
|
27099
27120
|
init_options2();
|
|
27100
27121
|
init_request2();
|
|
27122
|
+
init_thread_cache_periodic();
|
|
27101
27123
|
init_thread_info_realtime_sync();
|
|
27102
27124
|
init_state();
|
|
27103
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
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"autoUpdate": true,
|
|
3
3
|
"checkUpdate": {
|
|
4
4
|
"enabled": true,
|
|
5
|
-
"install":
|
|
6
|
-
"notifyIfCurrent":
|
|
5
|
+
"install": true,
|
|
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.
|
|
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",
|
|
@@ -69,7 +69,6 @@
|
|
|
69
69
|
"axios": "^1.13.5",
|
|
70
70
|
"axios-cookiejar-support": "^5.0.5",
|
|
71
71
|
"bluebird": "^3.7.2",
|
|
72
|
-
"boxen": "^8.0.1",
|
|
73
72
|
"cheerio": "^1.0.0-rc.10",
|
|
74
73
|
"cli-progress": "^3.12.0",
|
|
75
74
|
"duplexify": "^4.1.3",
|