sagor-fca 0.0.7 → 0.0.8
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 +2 -2
- package/func/checkUpdate.js +9 -12
- package/func/logAdapter.js +16 -19
- package/func/logger.js +47 -29
- package/index.js +12 -5
- package/module/config.js +20 -22
- package/module/login.js +78 -101
- package/module/loginHelper.js +3 -3
- package/module/options.js +26 -37
- package/package.json +2 -2
- package/src/api/action/addExternalModule.js +10 -16
- package/src/api/action/changeBio.js +18 -45
- package/src/api/action/enableAutoSaveAppState.js +52 -53
- package/src/api/action/getCurrentUserID.js +4 -0
- package/src/api/action/refreshFb_dtsg.js +51 -37
- package/src/api/feed/commentOnPost.js +120 -0
- package/src/api/feed/getPostInfo.js +98 -0
- package/src/api/groups/getGroupJoinRequests.js +126 -0
- package/src/api/groups/handleGroupJoinRequest.js +134 -0
- package/src/api/http/httpGet.js +14 -33
- package/src/api/http/httpPost.js +16 -37
- package/src/api/http/postFormData.js +14 -39
- package/src/api/messaging/notes.js +98 -0
- package/src/api/socket/core/connectMqtt.js +181 -175
- package/src/api/socket/core/emitAuth.js +50 -74
- package/src/api/socket/core/getSeqID.js +115 -267
- package/src/api/socket/core/getTaskResponseData.js +9 -7
- package/src/api/socket/detail/constants.js +5 -4
- package/src/api/socket/middleware/index.js +45 -181
- package/src/api/threads/getThreadPictures.js +31 -56
- package/src/api/users/getUserID.js +30 -56
- package/src/core/sendReqMqtt.js +29 -56
- package/src/database/helpers.js +14 -31
- package/src/database/models/index.js +38 -71
- package/src/database/models/thread.js +34 -40
- package/src/database/models/user.js +30 -37
- package/src/database/threadData.js +48 -50
- package/src/database/userData.js +38 -48
- package/src/remote/remoteClient.js +36 -88
- package/src/utils/broadcast.js +44 -34
- package/src/utils/client.js +7 -7
- package/src/utils/constants.js +35 -5
- package/src/utils/cookies.js +54 -49
- package/src/utils/format/s +0 -0
- package/src/utils/headers.js +72 -69
- package/src/utils/loginParser/s +0 -0
- package/src/utils/request/client.js +16 -10
- package/src/utils/request/config.js +17 -16
- package/src/utils/request/defaults.js +20 -26
- package/src/utils/request/helpers.js +12 -27
- package/src/utils/request/index.js +8 -13
- package/src/utils/request/methods.js +23 -105
- package/src/utils/request/proxy.js +10 -8
- package/src/utils/request/retry.js +51 -41
- package/src/utils/request/sanitize.js +17 -25
- package/src/utils/sessionKeeper.js +275 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
5
|
-
**Unofficial Facebook Chat API for Node.js
|
|
5
|
+
**Unofficial Facebook Chat API for Node.js**
|
|
6
6
|
|
|
7
7
|
</div>
|
|
8
8
|
|
|
@@ -113,7 +113,7 @@ login({ appState: [] }, (err, api) => {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
const yourID = "000000000000000"; // Replace with actual Facebook ID
|
|
116
|
-
const msg = "Hello
|
|
116
|
+
const msg = "Hello I'm SaGor bot👋";
|
|
117
117
|
|
|
118
118
|
api.sendMessage(msg, yourID, (err) => {
|
|
119
119
|
if (err) console.error("Message Sending Error:", err);
|
package/func/checkUpdate.js
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
// ============================================================
|
|
2
|
+
// SAGOR-FCA v2.0 — Check Update (Suspended)
|
|
3
|
+
// © 2025 Sagor. All Rights Reserved.
|
|
4
|
+
// autoUpdate Disabled — Does not slow down takeoff Render
|
|
5
|
+
// ============================================================
|
|
6
|
+
"use strict";
|
|
2
7
|
|
|
3
|
-
async function
|
|
4
|
-
|
|
5
|
-
return;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function checkAndUpdateVersion(callback) {
|
|
9
|
-
if (typeof callback === "function") {
|
|
10
|
-
_checkAndUpdateVersionImpl().then(() => callback(null)).catch(err => callback(err));
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
return _checkAndUpdateVersionImpl();
|
|
8
|
+
async function checkAndUpdateVersion() {
|
|
9
|
+
// ✅ Permanently disabled — does not check for updates
|
|
10
|
+
return Promise.resolve();
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
module.exports = { checkAndUpdateVersion };
|
package/func/logAdapter.js
CHANGED
|
@@ -1,33 +1,30 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// SAGOR-FCA v2.0 — Log Adapter
|
|
3
|
+
// © 2025 Sagor. All Rights Reserved.
|
|
4
|
+
// ============================================================
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
1
7
|
const logger = require("./logger");
|
|
2
8
|
|
|
3
9
|
function formatArgs(args) {
|
|
4
10
|
const [prefix, msg] = args;
|
|
5
|
-
|
|
6
|
-
// Single argument: log as-is
|
|
7
11
|
if (msg === undefined) {
|
|
8
|
-
if (prefix instanceof Error)
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
return String(prefix);
|
|
12
|
+
if (prefix instanceof Error) return prefix.stack || prefix.message || String(prefix);
|
|
13
|
+
return String(prefix ?? "");
|
|
12
14
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const base = msg.message || String(msg);
|
|
18
|
-
return tag ? `${tag}: ${base}` : base;
|
|
19
|
-
}
|
|
20
|
-
const text = msg == null ? "" : String(msg);
|
|
15
|
+
const tag = prefix == null ? "" : String(prefix);
|
|
16
|
+
const text = msg instanceof Error
|
|
17
|
+
? (msg.message || String(msg))
|
|
18
|
+
: (msg == null ? "" : String(msg));
|
|
21
19
|
return tag ? `${tag}: ${text}` : text;
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
const log = {
|
|
25
|
-
info:
|
|
26
|
-
warn:
|
|
27
|
-
error:
|
|
23
|
+
info: (...args) => logger(formatArgs(args), "info"),
|
|
24
|
+
warn: (...args) => logger(formatArgs(args), "warn"),
|
|
25
|
+
error: (...args) => logger(formatArgs(args), "error"),
|
|
28
26
|
verbose: (...args) => logger(formatArgs(args), "info"),
|
|
29
|
-
silly:
|
|
27
|
+
silly: (...args) => logger(formatArgs(args), "info"),
|
|
30
28
|
};
|
|
31
29
|
|
|
32
30
|
module.exports = log;
|
|
33
|
-
|
package/func/logger.js
CHANGED
|
@@ -1,48 +1,66 @@
|
|
|
1
|
-
|
|
1
|
+
// ============================================================
|
|
2
|
+
// SAGOR-FCA v2.0 — Logger
|
|
3
|
+
// © 2025 Sagor. All Rights Reserved.
|
|
4
|
+
// All rights reserved to Sagor
|
|
5
|
+
// ============================================================
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const chalk = require("chalk");
|
|
2
9
|
const gradient = require("gradient-string");
|
|
3
10
|
|
|
4
|
-
const
|
|
5
|
-
"blue",
|
|
11
|
+
const THEMES = [
|
|
12
|
+
"blue","dream2","dream","fiery","rainbow","pastel",
|
|
13
|
+
"cristal","red","aqua","pink","retro","sunlight",
|
|
14
|
+
"teen","summer","flower","ghost","hacker"
|
|
6
15
|
];
|
|
7
16
|
|
|
8
17
|
function buildGradient(name) {
|
|
9
18
|
const t = String(name || "").toLowerCase();
|
|
10
|
-
if (t === "blue")
|
|
11
|
-
if (t === "dream2")
|
|
12
|
-
if (t === "dream")
|
|
13
|
-
if (t === "fiery")
|
|
14
|
-
if (t === "rainbow")
|
|
15
|
-
if (t === "pastel")
|
|
16
|
-
if (t === "cristal")
|
|
17
|
-
if (t === "red")
|
|
18
|
-
if (t === "aqua")
|
|
19
|
-
if (t === "pink")
|
|
20
|
-
if (t === "retro")
|
|
21
|
-
if (t === "sunlight") return gradient("orange",
|
|
22
|
-
if (t === "teen")
|
|
23
|
-
if (t === "summer")
|
|
24
|
-
if (t === "flower")
|
|
25
|
-
if (t === "ghost")
|
|
26
|
-
if (t === "hacker")
|
|
27
|
-
return gradient("#243aff",
|
|
19
|
+
if (t === "blue") return gradient([{color:"#1affa3",pos:.2},{color:"cyan",pos:.4},{color:"pink",pos:.6},{color:"cyan",pos:.8},{color:"#1affa3",pos:1}]);
|
|
20
|
+
if (t === "dream2") return gradient("blue","pink");
|
|
21
|
+
if (t === "dream") return gradient([{color:"blue",pos:.2},{color:"pink",pos:.3},{color:"gold",pos:.6},{color:"pink",pos:.8},{color:"blue",pos:1}]);
|
|
22
|
+
if (t === "fiery") return gradient("#fc2803","#fc6f03","#fcba03");
|
|
23
|
+
if (t === "rainbow") return gradient.rainbow;
|
|
24
|
+
if (t === "pastel") return gradient.pastel;
|
|
25
|
+
if (t === "cristal") return gradient.cristal;
|
|
26
|
+
if (t === "red") return gradient("red","orange");
|
|
27
|
+
if (t === "aqua") return gradient("#0030ff","#4e6cf2");
|
|
28
|
+
if (t === "pink") return gradient("#d94fff","purple");
|
|
29
|
+
if (t === "retro") return gradient.retro;
|
|
30
|
+
if (t === "sunlight") return gradient("orange","#ffff00","#ffe600");
|
|
31
|
+
if (t === "teen") return gradient.teen;
|
|
32
|
+
if (t === "summer") return gradient.summer;
|
|
33
|
+
if (t === "flower") return gradient("blue","purple","yellow","#81ff6e");
|
|
34
|
+
if (t === "ghost") return gradient.mind;
|
|
35
|
+
if (t === "hacker") return gradient("#47a127","#0eed19","#27f231");
|
|
36
|
+
return gradient("#243aff","#4687f0","#5800d4");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const themeName = THEMES[Math.floor(Math.random() * THEMES.length)];
|
|
40
|
+
const co = buildGradient(themeName);
|
|
41
|
+
|
|
42
|
+
// ✅ Recording the times for each message facilitates diagnosis.
|
|
43
|
+
function timestamp() {
|
|
44
|
+
return new Date().toLocaleTimeString("en-US", { hour12: false });
|
|
28
45
|
}
|
|
29
46
|
|
|
30
|
-
|
|
31
|
-
const
|
|
47
|
+
module.exports = function logger(text, type) {
|
|
48
|
+
const s = String(type || "info").toLowerCase();
|
|
49
|
+
const ts = timestamp();
|
|
32
50
|
|
|
33
|
-
module.exports = (text, type) => {
|
|
34
|
-
const s = String(type || "info").toLowerCase();
|
|
35
51
|
if (s === "warn") {
|
|
36
|
-
process.stderr.write(co(`\r[
|
|
52
|
+
process.stderr.write(co(`\r[ SAGOR-WARN ][ ${ts} ] > ${text}`) + "\n");
|
|
37
53
|
return;
|
|
38
54
|
}
|
|
39
55
|
if (s === "error") {
|
|
40
|
-
process.stderr.write(
|
|
56
|
+
process.stderr.write(
|
|
57
|
+
chalk.bold.hex("#ff0000")(`\r[ SAGOR-ERROR ][ ${ts} ]`) + ` > ${text}\n`
|
|
58
|
+
);
|
|
41
59
|
return;
|
|
42
60
|
}
|
|
43
61
|
if (s === "info") {
|
|
44
|
-
process.stderr.write(chalk.bold(co(`\r[ FCA
|
|
62
|
+
process.stderr.write(chalk.bold(co(`\r[ SAGOR-FCA ][ ${ts} ] > ${text}`)) + "\n");
|
|
45
63
|
return;
|
|
46
64
|
}
|
|
47
|
-
process.stderr.write(chalk.bold(co(`\r[ ${s.toUpperCase()} ] > ${text}`)) + "\n");
|
|
65
|
+
process.stderr.write(chalk.bold(co(`\r[ ${s.toUpperCase()} ][ ${ts} ] > ${text}`)) + "\n");
|
|
48
66
|
};
|
package/index.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// SAGOR-FCA v2.0
|
|
3
|
+
// Facebook Chat API for Node.js
|
|
4
|
+
// © 2025 sagor. All Rights Reserved.
|
|
5
|
+
// All rights reserved to Sagor
|
|
6
|
+
//
|
|
7
|
+
// A library dedicated to the SAGOR bot
|
|
8
|
+
// It lasts for one month or more with AppState
|
|
9
|
+
// ============================================================
|
|
10
|
+
|
|
1
11
|
const login = require("./module/login");
|
|
2
12
|
|
|
3
|
-
|
|
4
|
-
module.exports
|
|
5
|
-
// Support require('{ login }') named import pattern
|
|
6
|
-
module.exports.login = login;
|
|
7
|
-
// Support ESM default import interop
|
|
13
|
+
module.exports = login;
|
|
14
|
+
module.exports.login = login;
|
|
8
15
|
module.exports.default = login;
|
|
9
16
|
module.exports.getRandomUserAgent = require("./src/utils/userAgent").getRandomUserAgent;
|
|
10
17
|
module.exports.userAgents = require("./src/utils/userAgent").userAgents;
|
package/module/config.js
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// ============================================================
|
|
2
|
+
// SAGOR-FCA v2.0 — Config Loader
|
|
3
|
+
// © 2025 Sagor. All Rights Reserved.
|
|
4
|
+
// ============================================================
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
7
|
+
const fs = require("fs");
|
|
8
|
+
const path = require("path");
|
|
3
9
|
const logger = require("../func/logger");
|
|
10
|
+
|
|
4
11
|
const defaultConfig = {
|
|
5
|
-
autoUpdate:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
antiGetInfo:
|
|
12
|
-
|
|
13
|
-
AntiGetUserInfo: false
|
|
14
|
-
},
|
|
15
|
-
remoteControl: {
|
|
16
|
-
enabled: false,
|
|
17
|
-
url: "",
|
|
18
|
-
token: "",
|
|
19
|
-
autoReconnect: true
|
|
20
|
-
}
|
|
12
|
+
autoUpdate: false,
|
|
13
|
+
autoLogin: false,
|
|
14
|
+
apiServer: "",
|
|
15
|
+
apiKey: "",
|
|
16
|
+
credentials: { email: "", password: "", twofactor: "" },
|
|
17
|
+
mqtt: { enabled: true, reconnectInterval: 3600 },
|
|
18
|
+
antiGetInfo: { AntiGetThreadInfo: false, AntiGetUserInfo: false },
|
|
19
|
+
remoteControl:{ enabled: false, url: "", token: "", autoReconnect: true }
|
|
21
20
|
};
|
|
22
21
|
|
|
23
22
|
function loadConfig() {
|
|
@@ -27,14 +26,13 @@ function loadConfig() {
|
|
|
27
26
|
config = defaultConfig;
|
|
28
27
|
} else {
|
|
29
28
|
try {
|
|
30
|
-
|
|
31
|
-
config = Object.assign({}, defaultConfig, JSON.parse(fileContent));
|
|
29
|
+
config = Object.assign({}, defaultConfig, JSON.parse(fs.readFileSync(configPath, "utf8")));
|
|
32
30
|
} catch (err) {
|
|
33
|
-
logger(`
|
|
31
|
+
logger(`[ SAGOR ] Reading error fca-config.json: ${err.message}`, "error");
|
|
34
32
|
config = defaultConfig;
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
35
|
return { config, configPath };
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
module.exports = { loadConfig, defaultConfig };
|
|
38
|
+
module.exports = { loadConfig, defaultConfig };
|
package/module/login.js
CHANGED
|
@@ -1,133 +1,110 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
// ============================================================
|
|
2
|
+
// SAGOR-FCA v2.0 — Login Entry Point
|
|
3
|
+
// © 2025 Sagor. All Rights Reserved.
|
|
4
|
+
//
|
|
5
|
+
// Library main entry point
|
|
6
|
+
// Integrates: Session Keeper + Anti-Crash + Auto-Save
|
|
7
|
+
// ============================================================
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
const { getType } = require("../src/utils/format");
|
|
11
|
+
const { setOptions }= require("./options");
|
|
12
|
+
const { loadConfig }= require("./config");
|
|
13
|
+
const loginHelper = require("./loginHelper");
|
|
14
|
+
const logger = require("../func/logger");
|
|
8
15
|
|
|
9
16
|
const { config } = loadConfig();
|
|
10
17
|
global.fca = { config };
|
|
11
18
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
global.fca._errorHandlersInstalled = true;
|
|
19
|
+
// ✅ Universal crash protection — just once
|
|
20
|
+
if (!global.fca._handlersInstalled) {
|
|
21
|
+
global.fca._handlersInstalled = true;
|
|
16
22
|
|
|
17
|
-
process.on("unhandledRejection", (reason
|
|
23
|
+
process.on("unhandledRejection", (reason) => {
|
|
18
24
|
try {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
errorCode === "ETIMEDOUT" ||
|
|
32
|
-
errorMessage.includes("Connect Timeout") ||
|
|
33
|
-
errorMessage.includes("fetch failed")) {
|
|
34
|
-
logger(`Network timeout error caught (non-fatal): ${errorMessage}`, "warn");
|
|
35
|
-
return; // Don't crash, just log
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Handle other network errors
|
|
39
|
-
if (errorCode === "ECONNREFUSED" ||
|
|
40
|
-
errorCode === "ENOTFOUND" ||
|
|
41
|
-
errorCode === "ECONNRESET" ||
|
|
42
|
-
errorMessage.includes("ECONNREFUSED") ||
|
|
43
|
-
errorMessage.includes("ENOTFOUND")) {
|
|
44
|
-
logger(`Network connection error caught (non-fatal): ${errorMessage}`, "warn");
|
|
45
|
-
return; // Don't crash, just log
|
|
46
|
-
}
|
|
25
|
+
if (!reason || typeof reason !== "object") return;
|
|
26
|
+
const code = reason.code || reason.cause?.code;
|
|
27
|
+
const msg = reason.message || String(reason);
|
|
28
|
+
|
|
29
|
+
if (msg.includes("No Sequelize instance passed")) return;
|
|
30
|
+
if (
|
|
31
|
+
code === "UND_ERR_CONNECT_TIMEOUT" || code === "ETIMEDOUT" ||
|
|
32
|
+
code === "ECONNREFUSED" || code === "ENOTFOUND" || code === "ECONNRESET" ||
|
|
33
|
+
msg.includes("Connect Timeout") || msg.includes("fetch failed")
|
|
34
|
+
) {
|
|
35
|
+
logger(`[ SAGOR ] Network error (will not stop the bot): ${msg}`, "warn");
|
|
36
|
+
return;
|
|
47
37
|
}
|
|
48
38
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
} catch (e) {
|
|
52
|
-
// Fallback if logger fails - silent
|
|
53
|
-
}
|
|
39
|
+
logger(`[ SAGOR ] Promise Untreated: ${reason?.message || String(reason)}`, "error");
|
|
40
|
+
} catch (_) {}
|
|
54
41
|
});
|
|
55
42
|
|
|
56
|
-
// Handle uncaught exceptions (last resort)
|
|
57
43
|
process.on("uncaughtException", (error) => {
|
|
58
44
|
try {
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
// Suppress Sequelize instance errors (handled gracefully in getBackupModel)
|
|
63
|
-
if (errorMessage.includes("No Sequelize instance passed")) {
|
|
64
|
-
return; // Silently ignore - already handled
|
|
65
|
-
}
|
|
45
|
+
const msg = error.message || String(error);
|
|
46
|
+
const code = error.code;
|
|
66
47
|
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
logger(`Uncaught network
|
|
73
|
-
return;
|
|
48
|
+
if (msg.includes("No Sequelize instance passed")) return;
|
|
49
|
+
if (
|
|
50
|
+
code === "UND_ERR_CONNECT_TIMEOUT" || code === "ETIMEDOUT" ||
|
|
51
|
+
msg.includes("Connect Timeout") || msg.includes("fetch failed")
|
|
52
|
+
) {
|
|
53
|
+
logger(`[ SAGOR ] Uncaught network error (will not stop the bot): ${msg}`, "warn");
|
|
54
|
+
return;
|
|
74
55
|
}
|
|
75
56
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Note: We don't exit here to allow bot to continue running
|
|
79
|
-
// In production, you might want to restart the process instead
|
|
80
|
-
} catch (e) {
|
|
81
|
-
// Fallback if logger fails - silent
|
|
82
|
-
}
|
|
57
|
+
logger(`[ SAGOR ] Unexpected error (the bot continues): ${msg}`, "error");
|
|
58
|
+
} catch (_) {}
|
|
83
59
|
});
|
|
84
60
|
}
|
|
85
61
|
|
|
86
62
|
function login(loginData, options, callback) {
|
|
87
63
|
if (getType(options) === "Function" || getType(options) === "AsyncFunction") {
|
|
88
64
|
callback = options;
|
|
89
|
-
options
|
|
65
|
+
options = {};
|
|
90
66
|
}
|
|
67
|
+
|
|
91
68
|
const globalOptions = {
|
|
92
|
-
selfListen:
|
|
93
|
-
selfListenEvent:
|
|
94
|
-
listenEvents:
|
|
95
|
-
listenTyping:
|
|
96
|
-
updatePresence:
|
|
97
|
-
forceLogin:
|
|
98
|
-
autoMarkRead:
|
|
99
|
-
autoReconnect:
|
|
100
|
-
online:
|
|
101
|
-
emitReady:
|
|
102
|
-
userAgent:
|
|
69
|
+
selfListen: false,
|
|
70
|
+
selfListenEvent: false,
|
|
71
|
+
listenEvents: false,
|
|
72
|
+
listenTyping: false,
|
|
73
|
+
updatePresence: false,
|
|
74
|
+
forceLogin: false,
|
|
75
|
+
autoMarkRead: false,
|
|
76
|
+
autoReconnect: true,
|
|
77
|
+
online: true,
|
|
78
|
+
emitReady: false,
|
|
79
|
+
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
|
|
103
80
|
};
|
|
81
|
+
|
|
104
82
|
setOptions(globalOptions, options);
|
|
105
|
-
|
|
106
|
-
let rejectFunc = null;
|
|
107
|
-
|
|
108
|
-
let returnPromise = null;
|
|
83
|
+
|
|
84
|
+
let prCallback = null, resolveFunc = null, rejectFunc = null, returnPromise = null;
|
|
85
|
+
|
|
109
86
|
if (getType(callback) !== "Function" && getType(callback) !== "AsyncFunction") {
|
|
110
|
-
returnPromise = new Promise(
|
|
87
|
+
returnPromise = new Promise((resolve, reject) => {
|
|
111
88
|
resolveFunc = resolve;
|
|
112
|
-
rejectFunc
|
|
89
|
+
rejectFunc = reject;
|
|
113
90
|
});
|
|
114
|
-
prCallback =
|
|
115
|
-
|
|
116
|
-
return resolveFunc(api);
|
|
117
|
-
};
|
|
118
|
-
callback = prCallback;
|
|
119
|
-
}
|
|
120
|
-
const proceed = () => loginHelper(loginData.appState, loginData.Cookie, loginData.email, loginData.password, globalOptions, callback, prCallback);
|
|
121
|
-
if (config && config.autoUpdate) {
|
|
122
|
-
const p = checkAndUpdateVersion();
|
|
123
|
-
if (p && typeof p.then === "function") {
|
|
124
|
-
p.then(proceed).catch(err => callback(err));
|
|
125
|
-
} else {
|
|
126
|
-
proceed();
|
|
127
|
-
}
|
|
128
|
-
} else {
|
|
129
|
-
proceed();
|
|
91
|
+
prCallback = (error, api) => error ? rejectFunc(error) : resolveFunc(api);
|
|
92
|
+
callback = prCallback;
|
|
130
93
|
}
|
|
94
|
+
|
|
95
|
+
// ✅ No autoUpdate — Instant startup
|
|
96
|
+
const proceed = () =>
|
|
97
|
+
loginHelper(
|
|
98
|
+
loginData.appState,
|
|
99
|
+
loginData.Cookie,
|
|
100
|
+
loginData.email,
|
|
101
|
+
loginData.password,
|
|
102
|
+
globalOptions,
|
|
103
|
+
callback,
|
|
104
|
+
prCallback
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
proceed();
|
|
131
108
|
return returnPromise;
|
|
132
109
|
}
|
|
133
110
|
|
package/module/loginHelper.js
CHANGED
|
@@ -1071,7 +1071,7 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
|
|
|
1071
1071
|
const userDataMatch = String(html).match(/\["CurrentUserInitialData",\[\],({.*?}),\d+\]/);
|
|
1072
1072
|
if (userDataMatch) {
|
|
1073
1073
|
const info = JSON.parse(userDataMatch[1]);
|
|
1074
|
-
logger(
|
|
1074
|
+
logger(`Đăng nhập tài khoản: ${info.NAME} (${info.USER_ID})`, "info");
|
|
1075
1075
|
|
|
1076
1076
|
// Check if Facebook response shows USER_ID = 0 (session dead)
|
|
1077
1077
|
if (!isValidUID(info.USER_ID)) {
|
|
@@ -1087,7 +1087,7 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
|
|
|
1087
1087
|
}
|
|
1088
1088
|
}
|
|
1089
1089
|
} else if (userID) {
|
|
1090
|
-
logger(`
|
|
1090
|
+
logger(`ID người dùng: ${userID}`, "info");
|
|
1091
1091
|
}
|
|
1092
1092
|
} catch (userDataErr) {
|
|
1093
1093
|
// If error is from our validation, rethrow it
|
|
@@ -1120,7 +1120,7 @@ function loginHelper(appState, Cookie, email, password, globalOptions, callback)
|
|
|
1120
1120
|
logger(`Database connection failed: ${errorMsg}`, "warn");
|
|
1121
1121
|
}
|
|
1122
1122
|
});
|
|
1123
|
-
logger("FCA
|
|
1123
|
+
logger("FCA fix/update by DongDev (Donix-VN)", "info");
|
|
1124
1124
|
const emitter = new EventEmitter();
|
|
1125
1125
|
const ctxMain = {
|
|
1126
1126
|
userID,
|
package/module/options.js
CHANGED
|
@@ -1,48 +1,37 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// SAGOR-FCA v2.0 — Options Handler
|
|
3
|
+
// © 2025 Sagor. All Rights Reserved.
|
|
4
|
+
// ============================================================
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
1
7
|
const { getType } = require("../src/utils/format");
|
|
2
8
|
const { setProxy } = require("../src/utils/request");
|
|
3
|
-
const { getRandomUserAgent } = require("../src/utils/userAgent");
|
|
4
9
|
const logger = require("../func/logger");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"selfListen",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"forceLogin",
|
|
11
|
-
"autoMarkRead",
|
|
12
|
-
"listenTyping",
|
|
13
|
-
"autoReconnect",
|
|
14
|
-
"emitReady",
|
|
15
|
-
"selfListenEvent",
|
|
16
|
-
"autoMarkDelivery"
|
|
10
|
+
|
|
11
|
+
const BOOL_OPTIONS = [
|
|
12
|
+
"online","selfListen","listenEvents","updatePresence","forceLogin",
|
|
13
|
+
"autoMarkRead","autoMarkDelivery","listenTyping","autoReconnect",
|
|
14
|
+
"emitReady","selfListenEvent"
|
|
17
15
|
];
|
|
16
|
+
|
|
17
|
+
// Old options are being silently ignored
|
|
18
|
+
const IGNORED = new Set(["logLevel","pauseLog","logRecordSize","updateSeq"]);
|
|
19
|
+
|
|
18
20
|
function setOptions(globalOptions, options) {
|
|
19
21
|
for (const key of Object.keys(options || {})) {
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
22
|
+
if (IGNORED.has(key)) continue;
|
|
23
|
+
if (BOOL_OPTIONS.includes(key)) { globalOptions[key] = Boolean(options[key]); continue; }
|
|
24
24
|
switch (key) {
|
|
25
|
-
case "userAgent":
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
case "notes":
|
|
31
|
-
case "proxy": {
|
|
32
|
-
if (typeof options.proxy !== "string") {
|
|
33
|
-
delete globalOptions.proxy;
|
|
34
|
-
setProxy();
|
|
35
|
-
} else {
|
|
36
|
-
globalOptions.proxy = options.proxy;
|
|
37
|
-
setProxy(globalOptions.proxy);
|
|
38
|
-
}
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
default: {
|
|
42
|
-
logger("setOptions Unrecognized option given to setOptions: " + key, "warn");
|
|
25
|
+
case "userAgent": globalOptions.userAgent = options.userAgent; break;
|
|
26
|
+
case "pageID": globalOptions.pageID = String(options.pageID); break;
|
|
27
|
+
case "proxy":
|
|
28
|
+
if (typeof options.proxy !== "string") { delete globalOptions.proxy; setProxy(); }
|
|
29
|
+
else { globalOptions.proxy = options.proxy; setProxy(options.proxy); }
|
|
43
30
|
break;
|
|
44
|
-
|
|
31
|
+
default:
|
|
32
|
+
logger(`[ SAGOR ] setOptions: Unknown option "${key}"`, "warn");
|
|
45
33
|
}
|
|
46
34
|
}
|
|
47
35
|
}
|
|
48
|
-
|
|
36
|
+
|
|
37
|
+
module.exports = { setOptions, BOOL_OPTIONS };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sagor-fca",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "The most powerful and updated Facebook Chat API (FCA).Enhanced by SaGor.",
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"description": "The most powerful and updated Facebook Chat API (FCA) with reverse-engineered fixes for GraphQL and MQTT. Enhanced by SaGor.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -1,25 +1,19 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// SAGOR-FCA v2.0 — Add External Module
|
|
3
|
+
// © 2025 Sagor. All Rights Reserved.
|
|
4
|
+
// ============================================================
|
|
1
5
|
"use strict";
|
|
2
6
|
|
|
3
7
|
const { getType } = require("../../utils/format");
|
|
4
8
|
|
|
5
9
|
module.exports = function(defaultFuncs, api, ctx) {
|
|
6
10
|
return function addExternalModule(moduleObj) {
|
|
7
|
-
if (getType(moduleObj)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
`Item "${apiName}" in moduleObj must be a function, not ${getType(
|
|
14
|
-
moduleObj[apiName]
|
|
15
|
-
)}!`
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
} else {
|
|
20
|
-
throw new Error(
|
|
21
|
-
`moduleObj must be an object, not ${getType(moduleObj)}!`
|
|
22
|
-
);
|
|
11
|
+
if (getType(moduleObj) !== "Object")
|
|
12
|
+
throw new Error(`moduleObj It must be an object, not ${getType(moduleObj)}`);
|
|
13
|
+
for (const name in moduleObj) {
|
|
14
|
+
if (getType(moduleObj[name]) !== "Function")
|
|
15
|
+
throw new Error(`"${name}" It should be Function`);
|
|
16
|
+
api[name] = moduleObj[name](defaultFuncs, api, ctx);
|
|
23
17
|
}
|
|
24
18
|
};
|
|
25
19
|
};
|