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.
Files changed (56) hide show
  1. package/README.md +2 -2
  2. package/func/checkUpdate.js +9 -12
  3. package/func/logAdapter.js +16 -19
  4. package/func/logger.js +47 -29
  5. package/index.js +12 -5
  6. package/module/config.js +20 -22
  7. package/module/login.js +78 -101
  8. package/module/loginHelper.js +3 -3
  9. package/module/options.js +26 -37
  10. package/package.json +2 -2
  11. package/src/api/action/addExternalModule.js +10 -16
  12. package/src/api/action/changeBio.js +18 -45
  13. package/src/api/action/enableAutoSaveAppState.js +52 -53
  14. package/src/api/action/getCurrentUserID.js +4 -0
  15. package/src/api/action/refreshFb_dtsg.js +51 -37
  16. package/src/api/feed/commentOnPost.js +120 -0
  17. package/src/api/feed/getPostInfo.js +98 -0
  18. package/src/api/groups/getGroupJoinRequests.js +126 -0
  19. package/src/api/groups/handleGroupJoinRequest.js +134 -0
  20. package/src/api/http/httpGet.js +14 -33
  21. package/src/api/http/httpPost.js +16 -37
  22. package/src/api/http/postFormData.js +14 -39
  23. package/src/api/messaging/notes.js +98 -0
  24. package/src/api/socket/core/connectMqtt.js +181 -175
  25. package/src/api/socket/core/emitAuth.js +50 -74
  26. package/src/api/socket/core/getSeqID.js +115 -267
  27. package/src/api/socket/core/getTaskResponseData.js +9 -7
  28. package/src/api/socket/detail/constants.js +5 -4
  29. package/src/api/socket/middleware/index.js +45 -181
  30. package/src/api/threads/getThreadPictures.js +31 -56
  31. package/src/api/users/getUserID.js +30 -56
  32. package/src/core/sendReqMqtt.js +29 -56
  33. package/src/database/helpers.js +14 -31
  34. package/src/database/models/index.js +38 -71
  35. package/src/database/models/thread.js +34 -40
  36. package/src/database/models/user.js +30 -37
  37. package/src/database/threadData.js +48 -50
  38. package/src/database/userData.js +38 -48
  39. package/src/remote/remoteClient.js +36 -88
  40. package/src/utils/broadcast.js +44 -34
  41. package/src/utils/client.js +7 -7
  42. package/src/utils/constants.js +35 -5
  43. package/src/utils/cookies.js +54 -49
  44. package/src/utils/format/s +0 -0
  45. package/src/utils/headers.js +72 -69
  46. package/src/utils/loginParser/s +0 -0
  47. package/src/utils/request/client.js +16 -10
  48. package/src/utils/request/config.js +17 -16
  49. package/src/utils/request/defaults.js +20 -26
  50. package/src/utils/request/helpers.js +12 -27
  51. package/src/utils/request/index.js +8 -13
  52. package/src/utils/request/methods.js +23 -105
  53. package/src/utils/request/proxy.js +10 -8
  54. package/src/utils/request/retry.js +51 -41
  55. package/src/utils/request/sanitize.js +17 -25
  56. 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 - The Ultimate Edition**
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 from sagor-fca! 👋";
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);
@@ -1,16 +1,13 @@
1
- const logger = require("./logger");
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 _checkAndUpdateVersionImpl() {
4
- logger("Auto-update is disabled for fca-unofficial-updated to maintain custom fixes.", "info");
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 };
@@ -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
- return prefix.stack || prefix.message || String(prefix);
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
- // Two arguments: mimic npmlog("tag", message)
15
- const tag = prefix == null ? "" : String(prefix);
16
- if (msg instanceof Error) {
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: (...args) => logger(formatArgs(args), "info"),
26
- warn: (...args) => logger(formatArgs(args), "warn"),
27
- error: (...args) => logger(formatArgs(args), "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: (...args) => logger(formatArgs(args), "info")
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
- const chalk = require("chalk");
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 themes = [
5
- "blue", "dream2", "dream", "fiery", "rainbow", "pastel", "cristal", "red", "aqua", "pink", "retro", "sunlight", "teen", "summer", "flower", "ghost", "hacker"
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") return gradient([{ color: "#1affa3", pos: 0.2 }, { color: "cyan", pos: 0.4 }, { color: "pink", pos: 0.6 }, { color: "cyan", pos: 0.8 }, { color: "#1affa3", pos: 1 }]);
11
- if (t === "dream2") return gradient("blue", "pink");
12
- if (t === "dream") return gradient([{ color: "blue", pos: 0.2 }, { color: "pink", pos: 0.3 }, { color: "gold", pos: 0.6 }, { color: "pink", pos: 0.8 }, { color: "blue", pos: 1 }]);
13
- if (t === "fiery") return gradient("#fc2803", "#fc6f03", "#fcba03");
14
- if (t === "rainbow") return gradient.rainbow;
15
- if (t === "pastel") return gradient.pastel;
16
- if (t === "cristal") return gradient.cristal;
17
- if (t === "red") return gradient("red", "orange");
18
- if (t === "aqua") return gradient("#0030ff", "#4e6cf2");
19
- if (t === "pink") return gradient("#d94fff", "purple");
20
- if (t === "retro") return gradient.retro;
21
- if (t === "sunlight") return gradient("orange", "#ffff00", "#ffe600");
22
- if (t === "teen") return gradient.teen;
23
- if (t === "summer") return gradient.summer;
24
- if (t === "flower") return gradient("blue", "purple", "yellow", "#81ff6e");
25
- if (t === "ghost") return gradient.mind;
26
- if (t === "hacker") return gradient("#47a127", "#0eed19", "#27f231");
27
- return gradient("#243aff", "#4687f0", "#5800d4");
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
- const themeName = themes[Math.floor(Math.random() * themes.length)];
31
- const co = buildGradient(themeName);
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[ FCA-WARN ] > ${text}`) + "\n");
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(chalk.bold.hex("#ff0000")(`\r[ FCA-ERROR ]`) + ` > ${text}\n`);
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-SAGOR ] > ${text}`)) + "\n");
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
- // 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
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
- const fs = require("fs");
2
- const path = require("path");
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: false,
6
- mqtt: { enabled: true, reconnectInterval: 3600 },
7
- autoLogin: true,
8
- apiServer: "https://minhdong.site",
9
- apiKey: "",
10
- credentials: { email: "", password: "", twofactor: "" },
11
- antiGetInfo: {
12
- AntiGetThreadInfo: false,
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
- const fileContent = fs.readFileSync(configPath, "utf8");
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(`Error reading config file: ${err.message}`, "error");
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
- const { getType } = require("../src/utils/format");
2
- const { setOptions } = require("./options");
3
- const { getRandomUserAgent } = require("../src/utils/userAgent");
4
- const { loadConfig } = require("./config");
5
- const { checkAndUpdateVersion } = require("../func/checkUpdate");
6
- const loginHelper = require("./loginHelper");
7
- const logger = require("../func/logger");
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
- // Global error handlers to prevent bot crashes
13
- // Handle unhandled promise rejections (e.g., fetch timeouts, network errors)
14
- if (!global.fca._errorHandlersInstalled) {
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, promise) => {
23
+ process.on("unhandledRejection", (reason) => {
18
24
  try {
19
- // Check if it's a fetch/network timeout error
20
- if (reason && typeof reason === "object") {
21
- const errorCode = reason.code || reason.cause?.code;
22
- const errorMessage = reason.message || String(reason);
23
-
24
- // Suppress Sequelize instance errors (handled gracefully in getBackupModel)
25
- if (errorMessage.includes("No Sequelize instance passed")) {
26
- return; // Silently ignore - already handled
27
- }
28
-
29
- // Handle fetch timeout errors gracefully
30
- if (errorCode === "UND_ERR_CONNECT_TIMEOUT" ||
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
- // For other unhandled rejections, log but don't crash
50
- logger(`Unhandled promise rejection (non-fatal): ${reason && reason.message ? reason.message : String(reason)}`, "error");
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 errorMessage = error.message || String(error);
60
- const errorCode = error.code;
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
- // Handle fetch/network errors
68
- if (errorCode === "UND_ERR_CONNECT_TIMEOUT" ||
69
- errorCode === "ETIMEDOUT" ||
70
- errorMessage.includes("Connect Timeout") ||
71
- errorMessage.includes("fetch failed")) {
72
- logger(`Uncaught network timeout error (non-fatal): ${errorMessage}`, "warn");
73
- return; // Don't crash
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
- // For other uncaught exceptions, log but try to continue
77
- logger(`Uncaught exception (attempting to continue): ${errorMessage}`, "error");
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: false,
93
- selfListenEvent: false,
94
- listenEvents: false,
95
- listenTyping: false,
96
- updatePresence: false,
97
- forceLogin: false,
98
- autoMarkRead: false,
99
- autoReconnect: true,
100
- online: true,
101
- emitReady: false,
102
- userAgent: getRandomUserAgent()
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
- let prCallback = null;
106
- let rejectFunc = null;
107
- let resolveFunc = null;
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(function (resolve, reject) {
87
+ returnPromise = new Promise((resolve, reject) => {
111
88
  resolveFunc = resolve;
112
- rejectFunc = reject;
89
+ rejectFunc = reject;
113
90
  });
114
- prCallback = function (error, api) {
115
- if (error) return rejectFunc(error);
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
 
@@ -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(`Log in to your account: ${info.NAME} (${info.USER_ID})`, "info");
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(`User ID: ${userID}`, "info");
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 UPDATE BY SAGOR 🧸", "info");
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
- const Boolean_Option = [
6
- "online",
7
- "selfListen",
8
- "listenEvents",
9
- "updatePresence",
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 (Boolean_Option.includes(key)) {
21
- globalOptions[key] = Boolean(options[key]);
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
- globalOptions.userAgent = options.userAgent || getRandomUserAgent();
27
- break;
28
- }
29
- case "logLevel":
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
- module.exports = { setOptions, Boolean_Option };
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.7",
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) == "Object") {
8
- for (const apiName in moduleObj) {
9
- if (getType(moduleObj[apiName]) == "Function") {
10
- api[apiName] = moduleObj[apiName](defaultFuncs, api, ctx);
11
- } else {
12
- throw new Error(
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
  };