@dongdev/fca-unofficial 2.0.27 → 2.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/func/checkUpdate.js +133 -48
- package/index.d.ts +13 -6
- package/index.js +8 -1
- package/package.json +9 -1
- package/src/api/socket/core/getSeqID.js +2 -1
package/CHANGELOG.md
CHANGED
package/func/checkUpdate.js
CHANGED
|
@@ -1,62 +1,147 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const PACKAGE_NAME = 'fca-unofficial';
|
|
8
|
+
// Không thử cài đặt lại trong vòng 10 phút sau lần update gần nhất
|
|
9
|
+
const LOCK_TTL_MS = 10 * 60 * 1000;
|
|
10
|
+
// Không check quá 1 lần mỗi 12 giờ
|
|
11
|
+
const CHECK_TTL_MS = 12 * 60 * 60 * 1000;
|
|
12
|
+
|
|
13
|
+
const lockPath = path.join(os.tmpdir(), 'fca-unofficial-update.lock');
|
|
14
|
+
const statePath = path.join(os.tmpdir(), 'fca-unofficial-update-state.json');
|
|
15
|
+
|
|
16
|
+
function readJSON(p) {
|
|
17
|
+
try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; }
|
|
18
|
+
}
|
|
19
|
+
function writeJSON(p, obj) {
|
|
20
|
+
try { fs.writeFileSync(p, JSON.stringify(obj)); } catch { }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isLockFresh() {
|
|
24
|
+
try {
|
|
25
|
+
const st = fs.statSync(lockPath);
|
|
26
|
+
return (Date.now() - st.mtimeMs) < LOCK_TTL_MS;
|
|
27
|
+
} catch { return false; }
|
|
28
|
+
}
|
|
29
|
+
function acquireLock() {
|
|
30
|
+
if (isLockFresh()) return false;
|
|
31
|
+
try { fs.writeFileSync(lockPath, String(Date.now())); return true; } catch { return false; }
|
|
32
|
+
}
|
|
33
|
+
function releaseLock() {
|
|
34
|
+
try { fs.unlinkSync(lockPath); } catch { }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function semverCompare(a, b) {
|
|
38
|
+
const pa = String(a).replace(/^v/, '').split('.').map(n => parseInt(n || 0, 10));
|
|
39
|
+
const pb = String(b).replace(/^v/, '').split('.').map(n => parseInt(n || 0, 10));
|
|
40
|
+
for (let i = 0; i < 3; i++) {
|
|
41
|
+
const da = pa[i] || 0, db = pb[i] || 0;
|
|
42
|
+
if (da > db) return 1;
|
|
43
|
+
if (da < db) return -1;
|
|
44
|
+
}
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getLatestVersion(pkgName) {
|
|
8
49
|
return new Promise((resolve, reject) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
50
|
+
const url = `https://registry.npmjs.org/${encodeURIComponent(pkgName)}/latest`;
|
|
51
|
+
https.get(url, res => {
|
|
52
|
+
let d = '';
|
|
53
|
+
res.setEncoding('utf8');
|
|
54
|
+
res.on('data', c => d += c);
|
|
55
|
+
res.on('end', () => {
|
|
56
|
+
try {
|
|
57
|
+
const j = JSON.parse(d);
|
|
58
|
+
resolve(j.version || null);
|
|
59
|
+
} catch (e) { reject(e); }
|
|
60
|
+
});
|
|
61
|
+
}).on('error', reject);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function runNpmInstallLatest(pkgName, cwd) {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const bin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
68
|
+
const child = spawn(bin, ['i', `${pkgName}@latest`], {
|
|
69
|
+
cwd,
|
|
70
|
+
stdio: 'inherit',
|
|
71
|
+
env: process.env
|
|
72
|
+
});
|
|
73
|
+
child.on('exit', code => {
|
|
74
|
+
if (code === 0) resolve();
|
|
75
|
+
else reject(new Error(`npm install exited with ${code}`));
|
|
12
76
|
});
|
|
77
|
+
child.on('error', reject);
|
|
13
78
|
});
|
|
14
79
|
}
|
|
15
80
|
|
|
16
|
-
|
|
81
|
+
// options: { cwd, pkg, restart }
|
|
82
|
+
async function checkUpdate(options = {}) {
|
|
83
|
+
if (global.__FCA_UPDATE_CHECKED__) return;
|
|
84
|
+
global.__FCA_UPDATE_CHECKED__ = true;
|
|
85
|
+
|
|
86
|
+
const pkg = options.pkg || PACKAGE_NAME;
|
|
87
|
+
const cwd = options.cwd || process.cwd();
|
|
88
|
+
const shouldRestart = options.restart !== false;
|
|
89
|
+
|
|
90
|
+
// Giới hạn tần suất check
|
|
91
|
+
const state = readJSON(statePath) || {};
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
if (state.lastCheck && now - state.lastCheck < CHECK_TTL_MS) return;
|
|
94
|
+
state.lastCheck = now;
|
|
95
|
+
writeJSON(statePath, state);
|
|
96
|
+
|
|
97
|
+
// Đọc version hiện tại
|
|
98
|
+
let currentVersion = null;
|
|
99
|
+
const installedPkgJson = path.join(cwd, 'node_modules', pkg, 'package.json');
|
|
100
|
+
const rootPkgJson = path.join(cwd, 'package.json');
|
|
101
|
+
|
|
102
|
+
const installed = readJSON(installedPkgJson);
|
|
103
|
+
if (installed && installed.version) {
|
|
104
|
+
currentVersion = installed.version;
|
|
105
|
+
} else {
|
|
106
|
+
// fallback: nếu lib đang là chính dự án
|
|
107
|
+
const root = readJSON(rootPkgJson);
|
|
108
|
+
if (root && root.name === pkg && root.version) {
|
|
109
|
+
currentVersion = root.version;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (!currentVersion) return; // Không xác định được version hiện tại => bỏ
|
|
113
|
+
|
|
114
|
+
let latestVersion = null;
|
|
17
115
|
try {
|
|
18
|
-
|
|
19
|
-
return JSON.parse(fs.readFileSync(p, "utf8")).version;
|
|
116
|
+
latestVersion = await getLatestVersion(pkg);
|
|
20
117
|
} catch {
|
|
21
|
-
return
|
|
118
|
+
return; // network lỗi => bỏ qua, tránh spam
|
|
22
119
|
}
|
|
23
|
-
|
|
120
|
+
if (!latestVersion) return;
|
|
24
121
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const latest = (await execPromise(`npm view ${pkgName} version`)).stdout.trim();
|
|
28
|
-
const installed = getInstalledVersion();
|
|
29
|
-
if (!installed || installed !== latest) {
|
|
30
|
-
logger(`New version available (${latest}). Current version (${installed || "not installed"}). Updating...`, "info");
|
|
31
|
-
try {
|
|
32
|
-
const { stderr } = await execPromise(`npm i ${pkgName}@latest`);
|
|
33
|
-
if (stderr) logger(stderr, "error");
|
|
34
|
-
logger(`Updated fca to the latest version: ${latest}, Restart to apply`, "info");
|
|
35
|
-
process.exit(1);
|
|
36
|
-
} catch (e) {
|
|
37
|
-
logger(`Error running npm install: ${e.error || e}. Trying to install from GitHub...`, "error");
|
|
38
|
-
try {
|
|
39
|
-
const { stderr } = await execPromise("npm i https://github.com/Donix-VN/fca-unofficial");
|
|
40
|
-
if (stderr) logger(stderr, "error");
|
|
41
|
-
logger(`Installed from GitHub successfully: ${latest}`, "info");
|
|
42
|
-
return;
|
|
43
|
-
} catch (gitErr) {
|
|
44
|
-
logger(`Error installing from GitHub: ${gitErr.error || gitErr}`, "error");
|
|
45
|
-
throw (gitErr.error || gitErr);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
logger(`You're already on the latest version - ${latest}`, "info");
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
122
|
+
// Nếu đã mới nhất => thôi
|
|
123
|
+
if (semverCompare(currentVersion, latestVersion) >= 0) return;
|
|
53
124
|
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
|
|
125
|
+
// Đã có lock mới => bỏ để tránh loop
|
|
126
|
+
if (!acquireLock()) return;
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
await runNpmInstallLatest(pkg, cwd);
|
|
130
|
+
|
|
131
|
+
// Sau khi cài xong, chỉ restart đúng 1 lần
|
|
132
|
+
if (shouldRestart) {
|
|
133
|
+
if (global.__FCA_RESTARTING__) return;
|
|
134
|
+
global.__FCA_RESTARTING__ = true;
|
|
135
|
+
// Dùng exit code riêng để process manager có thể phân biệt
|
|
136
|
+
setTimeout(() => process.exit(222), 300);
|
|
137
|
+
}
|
|
138
|
+
} catch (e) {
|
|
139
|
+
// Không restart khi cài thất bại để tránh loop
|
|
140
|
+
} finally {
|
|
141
|
+
// Không xóa lock ngay để tránh ngay-lập-tức retry sau restart
|
|
142
|
+
// Lock TTL sẽ tự hết hạn
|
|
143
|
+
// releaseLock(); // cố tình KHÔNG gọi
|
|
58
144
|
}
|
|
59
|
-
return _checkAndUpdateVersionImpl();
|
|
60
145
|
}
|
|
61
146
|
|
|
62
|
-
module.exports =
|
|
147
|
+
module.exports = checkUpdate;
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Origin: NOCOM-BOT/mod_fbmsg_legacy
|
|
1
|
+
// Origin: NOCOM-BOT/mod_fbmsg_legacy
|
|
2
2
|
|
|
3
3
|
declare module '@dongdev/fca-unofficial' {
|
|
4
4
|
import type { Readable, Duplex, Transform } from "stream";
|
|
@@ -8,25 +8,30 @@ declare module '@dongdev/fca-unofficial' {
|
|
|
8
8
|
function login(credentials: Partial<{
|
|
9
9
|
email: string,
|
|
10
10
|
password: string,
|
|
11
|
-
appState: AppstateData
|
|
11
|
+
appState: AppstateData,
|
|
12
|
+
Cookie?: string | string[] | Record<string,string>
|
|
12
13
|
}>, options: Partial<IFCAU_Options>, callback: (err: Error | null, api: IFCAU_API) => void): void;
|
|
13
14
|
function login(credentials: Partial<{
|
|
14
15
|
email: string,
|
|
15
16
|
password: string,
|
|
16
|
-
appState: AppstateData
|
|
17
|
+
appState: AppstateData,
|
|
18
|
+
Cookie?: string | string[] | Record<string,string>
|
|
17
19
|
}>, options: Partial<IFCAU_Options>): Promise<IFCAU_API>;
|
|
18
20
|
function login(credentials: Partial<{
|
|
19
21
|
email: string,
|
|
20
22
|
password: string,
|
|
21
|
-
appState: AppstateData
|
|
23
|
+
appState: AppstateData,
|
|
24
|
+
Cookie?: string | string[] | Record<string,string>
|
|
22
25
|
}>, callback: (err: Error | null, api: IFCAU_API) => void): void;
|
|
23
26
|
function login(credentials: Partial<{
|
|
24
27
|
email: string,
|
|
25
28
|
password: string,
|
|
26
|
-
appState: AppstateData
|
|
29
|
+
appState: AppstateData,
|
|
30
|
+
Cookie?: string | string[] | Record<string,string>
|
|
27
31
|
}>): Promise<IFCAU_API>;
|
|
28
32
|
|
|
29
|
-
export default login;
|
|
33
|
+
export default login;
|
|
34
|
+
export { login };
|
|
30
35
|
|
|
31
36
|
export type Cookie = {
|
|
32
37
|
key: string,
|
|
@@ -613,3 +618,5 @@ declare module '@dongdev/fca-unofficial' {
|
|
|
613
618
|
name: string
|
|
614
619
|
};
|
|
615
620
|
}
|
|
621
|
+
|
|
622
|
+
|
package/index.js
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
const login = require("./module/login");
|
|
2
|
+
|
|
3
|
+
// CommonJS default export
|
|
4
|
+
module.exports = login;
|
|
5
|
+
// Support require('{ login }') named import pattern
|
|
6
|
+
module.exports.login = login;
|
|
7
|
+
// Support ESM default import interop
|
|
8
|
+
module.exports.default = login;
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dongdev/fca-unofficial",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.29",
|
|
4
4
|
"description": "Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"require": "./index.js",
|
|
10
|
+
"default": "./index.js",
|
|
11
|
+
"types": "./index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
6
14
|
"scripts": {
|
|
7
15
|
"test": "mocha",
|
|
8
16
|
"lint": "eslint .",
|
|
@@ -25,7 +25,8 @@ module.exports = function createGetSeqID(deps) {
|
|
|
25
25
|
}
|
|
26
26
|
})
|
|
27
27
|
.catch(err => {
|
|
28
|
-
const
|
|
28
|
+
const detail = (err && err.detail && err.detail.message) ? ` | detail=${err.detail.message}` : "";
|
|
29
|
+
const msg = ((err && err.error) || (err && err.message) || String(err || "")) + detail;
|
|
29
30
|
if (/Not logged in/i.test(msg)) {
|
|
30
31
|
return emitAuth(ctx, api, globalCallback, "not_logged_in", msg);
|
|
31
32
|
}
|