shadowx-fca 2.7.0 → 2.8.0

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/checkUpdate.js CHANGED
@@ -15,7 +15,7 @@ async function checkForFCAUpdate() {
15
15
  const latestVersion = npmData.version;
16
16
 
17
17
  // Check current installed version in node_modules
18
- let currentVersion = '2.4.0';
18
+ let currentVersion = '1.0.8';
19
19
  const nodeModulesPackagePath = path.join(process.cwd(), 'node_modules', 'shadowx-fca', 'package.json');
20
20
  if (fs.existsSync(nodeModulesPackagePath)) {
21
21
  const installedPackage = JSON.parse(fs.readFileSync(nodeModulesPackagePath, 'utf-8'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadowx-fca",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "Unofficial Facebook Chat API for Node.js with Auto-Update System - modify by Mueid Mursalin Rifat",
5
5
  "main": "index.js",
6
6
  "files": [
package/src/listenMqtt.js CHANGED
@@ -10,6 +10,9 @@ const debugSeq = false;
10
10
  var identity = function () { };
11
11
  var form = {};
12
12
  var getSeqID = function () { };
13
+ var seqIdRetryCount = 0;
14
+ var MAX_SEQID_RETRIES = 3;
15
+
13
16
  var topics = [
14
17
  "/legacy_web",
15
18
  "/webrtc",
@@ -105,13 +108,20 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
105
108
  mqttClient.on('error', function (err) {
106
109
  log.error("listenMqtt", err);
107
110
  mqttClient.end();
108
- if (ctx.globalOptions.autoReconnect) getSeqID();
109
- else globalCallback({ type: "stop_listen", error: "Connection refused: Server unavailable" }, null);
111
+ if (ctx.globalOptions.autoReconnect) {
112
+ seqIdRetryCount = 0;
113
+ getSeqID();
114
+ } else {
115
+ globalCallback({ type: "stop_listen", error: "Connection refused: Server unavailable" }, null);
116
+ }
110
117
  });
111
118
 
112
119
  mqttClient.on('connect', function () {
113
120
  topics.forEach(topicsub => mqttClient.subscribe(topicsub));
114
121
 
122
+ // Reset retry count on successful connection
123
+ seqIdRetryCount = 0;
124
+
115
125
  // Display connection success message with branding and loading animation
116
126
  const messages = [
117
127
  '🖤 SHADOWX-FCA MQTT Connected',
@@ -787,6 +797,9 @@ module.exports = function (defaultFuncs, api, ctx) {
787
797
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
788
798
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
789
799
  .then((resData) => {
800
+ // Reset retry count on success
801
+ seqIdRetryCount = 0;
802
+
790
803
  if (utils.getType(resData) != "Array") throw { error: "Not logged in", res: resData };
791
804
  if (resData && resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
792
805
  if (resData[resData.length - 1].successful_results === 0) throw { error: "getSeqId: there was no successful_results", res: resData };
@@ -796,8 +809,37 @@ module.exports = function (defaultFuncs, api, ctx) {
796
809
  } else throw { error: "getSeqId: no sync_sequence_id found.", res: resData };
797
810
  })
798
811
  .catch((err) => {
812
+ // Check for binary response / JSON parse error
813
+ if (err.error && err.error.includes && err.error.includes("JSON.parse error")) {
814
+ seqIdRetryCount++;
815
+
816
+ if (seqIdRetryCount <= MAX_SEQID_RETRIES) {
817
+ log.warn("getSeqId", "Binary/JSON parse error (attempt " + seqIdRetryCount + "/" + MAX_SEQID_RETRIES + "). Retrying in " + (seqIdRetryCount * 3) + "s...");
818
+
819
+ setTimeout(() => {
820
+ api.getFreshDtsg().then(newDtsg => {
821
+ if (newDtsg) ctx.fb_dtsg = newDtsg;
822
+ }).catch(() => {}).finally(() => {
823
+ getSeqID();
824
+ });
825
+ }, seqIdRetryCount * 3000);
826
+ return;
827
+ }
828
+
829
+ log.warn("getSeqId", "MQTT sync failed after " + MAX_SEQID_RETRIES + " retries. Falling back to HTTP mode (bot will still work).");
830
+
831
+ // Emit ready so bot continues working
832
+ ctx.loggedIn = true;
833
+ if (ctx.globalOptions.emitReady) {
834
+ globalCallback({ type: "ready", error: null });
835
+ }
836
+ return;
837
+ }
838
+
799
839
  log.error("getSeqId", err);
800
- if (utils.getType(err) == "Object" && err.error === "Not logged in") ctx.loggedIn = false;
840
+ if (utils.getType(err) == "Object" && err.error === "Not logged in") {
841
+ ctx.loggedIn = false;
842
+ }
801
843
  return globalCallback(err);
802
844
  });
803
845
  };
package/utils.js CHANGED
@@ -2498,6 +2498,28 @@ function parseAndCheckLogin(ctx, defaultFuncs, retryCount) {
2498
2498
  }
2499
2499
  if (data.statusCode !== 200) throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
2500
2500
 
2501
+ // ⭐ FIX: Check for binary/gzipped response before parsing ⭐
2502
+ if (typeof data.body === 'string' &&
2503
+ (data.body.includes('\x00') || data.body.includes('\x1f\x8b') || data.body.includes('�') || data.body.includes('\x07'))) {
2504
+ log.warn("parseAndCheckLogin", "Binary/gzip response detected. Throwing recoverable error.");
2505
+ throw {
2506
+ error: "JSON.parse error. Check the `detail` property on this error.",
2507
+ detail: new Error("Binary response received"),
2508
+ res: data.body,
2509
+ isBinaryResponse: true
2510
+ };
2511
+ }
2512
+
2513
+ // Check for HTML login page (session expired)
2514
+ if (typeof data.body === 'string' &&
2515
+ (data.body.includes('<!DOCTYPE') || data.body.includes('<html') || data.body.includes('login_form'))) {
2516
+ log.warn("parseAndCheckLogin", "HTML login page detected. Session may be expired.");
2517
+ throw {
2518
+ error: "Not logged in.",
2519
+ res: data.body.substring(0, 500)
2520
+ };
2521
+ }
2522
+
2501
2523
  var res = null;
2502
2524
  try {
2503
2525
  res = JSON.parse(makeParsable(data.body));
@@ -2531,7 +2553,7 @@ function parseAndCheckLogin(ctx, defaultFuncs, retryCount) {
2531
2553
  }
2532
2554
  }
2533
2555
 
2534
- if (res.error === 1357001) throw { error: "Not logged in." };
2556
+ if (res.error === 1357001 || res.error === 1357004) throw { error: "Not logged in." };
2535
2557
  return res;
2536
2558
  });
2537
2559
  };