stfca 1.0.26 → 1.1.27

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/src/listenMqtt.js CHANGED
@@ -3,46 +3,219 @@
3
3
  var utils = require("../utils");
4
4
  var log = require("npmlog");
5
5
  var mqtt = require('mqtt');
6
- var websocket = require('websocket-stream');
7
- var HttpsProxyAgent = require('https-proxy-agent');
6
+ var WebSocket = require('ws');
7
+ var Transform = require('stream').Transform;
8
8
  const EventEmitter = require('events');
9
- const debugSeq = false;
9
+
10
+ // ─── ANSI colour helpers ───────────────────────────────────────────────────────
11
+ var C = {
12
+ reset: '\x1b[0m',
13
+ bold: '\x1b[1m',
14
+ dim: '\x1b[2m',
15
+ // foregrounds
16
+ black: '\x1b[30m',
17
+ red: '\x1b[31m',
18
+ green: '\x1b[32m',
19
+ yellow: '\x1b[33m',
20
+ blue: '\x1b[34m',
21
+ magenta: '\x1b[35m',
22
+ cyan: '\x1b[36m',
23
+ white: '\x1b[37m',
24
+ // bright foregrounds
25
+ bBlack: '\x1b[90m',
26
+ bRed: '\x1b[91m',
27
+ bGreen: '\x1b[92m',
28
+ bYellow: '\x1b[93m',
29
+ bBlue: '\x1b[94m',
30
+ bMagenta: '\x1b[95m',
31
+ bCyan: '\x1b[96m',
32
+ bWhite: '\x1b[97m',
33
+ // backgrounds
34
+ bgBlue: '\x1b[44m',
35
+ bgCyan: '\x1b[46m',
36
+ bgMagenta: '\x1b[45m',
37
+ bgGreen: '\x1b[42m',
38
+ bgBlack: '\x1b[40m',
39
+ };
40
+
41
+ // ─── MQTT Spinner ──────────────────────────────────────────────────────────────
42
+ var _mqttSpinner = null;
43
+
44
+ function startMqttSpinner(region) {
45
+ var frames = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
46
+ var fi = 0;
47
+ var regionStr = region ? (' ' + C.dim + C.bCyan + '[' + region.toUpperCase() + ']' + C.reset) : '';
48
+ process.stdout.write('\n');
49
+ _mqttSpinner = setInterval(function () {
50
+ var frame = frames[fi++ % frames.length];
51
+ process.stdout.write(
52
+ '\r ' +
53
+ C.bold + C.bCyan + frame + C.reset + ' ' +
54
+ C.cyan + 'ST-FCA' + C.reset + ' ' +
55
+ C.dim + 'connecting to MQTT' + C.reset +
56
+ regionStr +
57
+ C.dim + ' ...' + C.reset +
58
+ ' '
59
+ );
60
+ }, 80);
61
+ }
62
+
63
+ function stopMqttSpinner() {
64
+ if (_mqttSpinner) {
65
+ clearInterval(_mqttSpinner);
66
+ _mqttSpinner = null;
67
+ }
68
+ // erase the spinner line completely
69
+ process.stdout.write('\r\x1b[2K');
70
+ }
71
+
72
+ function printMqttBanner(region, autoReconnect) {
73
+ stopMqttSpinner();
74
+
75
+ var titleClr = C.bold + C.bGreen;
76
+ var labelClr = C.bold + C.bWhite;
77
+ var valClr = C.bYellow;
78
+ var accentClr = C.bold + C.bMagenta;
79
+ var urlClr = C.bBlue;
80
+ var rst = C.reset;
81
+
82
+ var regionVal = (region || '').toUpperCase();
83
+ var reconnTxt = autoReconnect ? 'Enabled (3s)' : 'Disabled';
84
+ var reconnClr = autoReconnect ? C.bGreen : C.bRed;
85
+ var reconnVal = reconnClr + reconnTxt + rst;
86
+
87
+ var rows = [
88
+ titleClr + ' ✅ ST-FCA MQTT Connected' + rst,
89
+ '',
90
+ labelClr + ' 📍 Region ' + rst + valClr + regionVal + rst,
91
+ labelClr + ' 🔄 Auto-reconnect ' + rst + reconnVal,
92
+ urlClr + ' 🌐 github.com/sheikhtamimlover/ST-BOT' + rst,
93
+ '',
94
+ accentClr + ' 💎 Author ST | Sheikh Tamim' + rst
95
+ ];
96
+
97
+ process.stdout.write('\n');
98
+ rows.forEach(function (line) {
99
+ console.log(line);
100
+ });
101
+ process.stdout.write('\n');
102
+ }
103
+
104
+ /**
105
+ * Facebook sends non-standard MQTT packets where PUBACK/SUBACK have
106
+ * non-zero reserved flag bits (e.g. 0x4F instead of 0x40).
107
+ * mqtt-packet strictly rejects these. This transform stream patches
108
+ * the first byte of each MQTT frame to clear the lower nibble (flags),
109
+ * keeping only the packet type (upper nibble).
110
+ *
111
+ * MQTT fixed header: byte[0] = (type << 4) | flags
112
+ * For PUBACK (type=4): valid = 0x40, FB may send 0x4F → we clear to 0x40
113
+ */
114
+ function createMqttPatchStream() {
115
+ var buf = null;
116
+
117
+ // Walk frame by frame. For types that must have flags=0 per the MQTT spec
118
+ // (CONNACK=2, PUBACK=4, SUBACK=9, UNSUBACK=11, PINGRESP=13), clear the
119
+ // lower nibble that Facebook sets to non-zero values.
120
+ var stream = new Transform({
121
+ transform: function (chunk, encoding, callback) {
122
+ if (!Buffer.isBuffer(chunk)) chunk = Buffer.from(chunk, encoding);
123
+
124
+ // Prepend any leftover bytes from the previous chunk
125
+ var out;
126
+ if (buf) {
127
+ out = Buffer.concat([buf, chunk]);
128
+ buf = null;
129
+ } else {
130
+ out = Buffer.from(chunk);
131
+ }
132
+
133
+ var i = 0;
134
+ while (i < out.length) {
135
+ var b = out[i];
136
+ var type = (b >> 4) & 0x0F;
137
+ var flags = b & 0x0F;
138
+ // Types that MUST have flags=0:
139
+ if (flags !== 0 && (type === 4 || type === 9 || type === 11 || type === 13 || type === 2)) {
140
+ out[i] = (b & 0xF0); // clear lower nibble
141
+ }
142
+ // Skip past this frame: read the varint length
143
+ i++;
144
+ var multiplier = 1;
145
+ var frameLen = 0;
146
+ var lenOk = false;
147
+ while (i < out.length) {
148
+ var lb = out[i++];
149
+ frameLen += (lb & 0x7F) * multiplier;
150
+ multiplier *= 128;
151
+ if ((lb & 0x80) === 0) { lenOk = true; break; }
152
+ if (multiplier > 128 * 128 * 128) break; // malformed
153
+ }
154
+ if (!lenOk) {
155
+ // Incomplete frame — save remainder for next chunk
156
+ buf = out.slice(i - 1);
157
+ out = out.slice(0, i - 1);
158
+ break;
159
+ }
160
+ i += frameLen;
161
+ }
162
+
163
+ callback(null, out);
164
+ },
165
+ flush: function (callback) {
166
+ if (buf && buf.length > 0) callback(null, buf);
167
+ else callback();
168
+ buf = null;
169
+ }
170
+ });
171
+ return stream;
172
+ }
173
+
10
174
  var identity = function () { };
11
175
  var form = {};
12
176
  var getSeqID = function () { };
177
+
13
178
  var topics = [
14
179
  "/legacy_web",
15
180
  "/webrtc",
16
181
  "/rtc_multi",
17
182
  "/onevc",
18
- "/br_sr", //Notification
19
- //Need to publish /br_sr right after this
183
+ "/br_sr",
20
184
  "/sr_res",
21
185
  "/t_ms",
22
186
  "/thread_typing",
23
187
  "/orca_typing_notifications",
24
188
  "/notify_disconnect",
25
- //Need to publish /messenger_sync_create_queue right after this
26
189
  "/orca_presence",
27
- //Will receive /sr_res right here.
28
-
29
190
  "/inbox",
30
191
  "/mercury",
31
192
  "/messaging_events",
32
193
  "/orca_message_notifications",
33
194
  "/pp",
34
195
  "/webrtc_response",
196
+ "/ls_resp"
35
197
  ];
36
198
 
199
+ function sanitizeHeaderValue(value) {
200
+ if (value === null || value === undefined) return "";
201
+ var str = String(value);
202
+ if (str.trim().startsWith("[") && str.trim().endsWith("]")) {
203
+ try {
204
+ var parsed = JSON.parse(str);
205
+ if (Array.isArray(parsed)) return "";
206
+ } catch (_) { }
207
+ }
208
+ str = str.replace(/[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F\r\n\[\]]/g, "").trim();
209
+ return str;
210
+ }
211
+
37
212
  function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
38
- //Don't really know what this does but I think it's for the active state?
39
- //TODO: Move to ctx when implemented
40
213
  var chatOn = ctx.globalOptions.online;
41
214
  var foreground = false;
42
-
43
215
  var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
44
216
  var GUID = utils.getGUID();
45
- const username = {
217
+
218
+ var username = {
46
219
  u: ctx.userID,
47
220
  s: sessionID,
48
221
  chat_on: chatOn,
@@ -63,86 +236,138 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
63
236
  p: null,
64
237
  php_override: ""
65
238
  };
66
- var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
67
239
 
240
+ var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
68
241
  var host;
69
- if (ctx.mqttEndpoint) host = `${ctx.mqttEndpoint}&sid=${sessionID}&cid=${GUID}`;
70
- else if (ctx.region) host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}&cid=${GUID}`;
71
- else host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}&cid=${GUID}`;
242
+ if (ctx.mqttEndpoint) {
243
+ // Ensure no duplicate sid/cid — strip any existing ones then append fresh
244
+ var baseEndpoint = ctx.mqttEndpoint
245
+ .replace(/[?&]sid=[^&]*/g, '')
246
+ .replace(/[?&]cid=[^&]*/g, '');
247
+ // Re-attach the ? if it was stripped along with the first param
248
+ if (baseEndpoint.indexOf('?') === -1 && ctx.mqttEndpoint.indexOf('?') !== -1) {
249
+ baseEndpoint = baseEndpoint.replace(/&/, '?');
250
+ }
251
+ var sep = baseEndpoint.indexOf('?') === -1 ? '?' : '&';
252
+ host = baseEndpoint + sep + "sid=" + sessionID + "&cid=" + GUID;
253
+ } else if (ctx.region) {
254
+ host = "wss://edge-chat.facebook.com/chat?region=" + ctx.region.toLowerCase() + "&sid=" + sessionID + "&cid=" + GUID;
255
+ } else {
256
+ host = "wss://edge-chat.facebook.com/chat?sid=" + sessionID + "&cid=" + GUID;
257
+ }
258
+
259
+ var ua = ctx.globalOptions.userAgent ||
260
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.4 Safari/605.1.15";
261
+
262
+ var wsHeaders = {
263
+ Cookie: sanitizeHeaderValue(cookies),
264
+ Origin: "https://www.facebook.com",
265
+ "User-Agent": sanitizeHeaderValue(ua),
266
+ Referer: "https://www.facebook.com/",
267
+ Host: "edge-chat.facebook.com",
268
+ Connection: "Upgrade",
269
+ Upgrade: "websocket",
270
+ "Sec-WebSocket-Version": "13",
271
+ "Sec-WebSocket-Extensions": "permessage-deflate; client_max_window_bits",
272
+ "Accept-Language": "en-US,en;q=0.9",
273
+ "Accept-Encoding": "gzip, deflate, br",
274
+ "Cache-Control": "no-cache",
275
+ Pragma: "no-cache"
276
+ };
277
+
278
+ if (ctx.region) wsHeaders["X-MSGR-Region"] = sanitizeHeaderValue(ctx.region);
72
279
 
73
- const options = {
74
- clientId: 'mqttwsclient',
75
- protocolId: 'MQIsdp',
280
+ var wsOptions = {
281
+ headers: wsHeaders,
282
+ origin: "https://www.facebook.com",
283
+ protocolVersion: 13,
284
+ binaryType: "arraybuffer"
285
+ };
286
+
287
+ if (typeof ctx.globalOptions.proxy !== "undefined") {
288
+ var { HttpsProxyAgent } = require('https-proxy-agent');
289
+ wsOptions.agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
290
+ }
291
+
292
+ var mqttOptions = {
293
+ clientId: "mqttwsclient",
294
+ protocolId: "MQIsdp",
76
295
  protocolVersion: 3,
77
296
  username: JSON.stringify(username),
78
297
  clean: true,
79
- wsOptions: {
80
- headers: {
81
- Cookie: cookies,
82
- Origin: 'https://www.facebook.com',
83
- 'User-Agent': ctx.globalOptions.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36',
84
- Referer: 'https://www.facebook.com/',
85
- Host: new URL(host).hostname,
86
- },
87
- origin: 'https://www.facebook.com',
88
- protocolVersion: 13,
89
- binaryType: 'arraybuffer',
90
- },
91
- keepalive: 60,
298
+ keepalive: 30,
92
299
  reschedulePings: true,
93
- reconnectPeriod: 3,
300
+ reconnectPeriod: 0,
301
+ connectTimeout: 12000
94
302
  };
95
303
 
96
- if (typeof ctx.globalOptions.proxy != "undefined") {
97
- var agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
98
- options.wsOptions.agent = agent;
304
+ // Use MqttClient with a proper Duplex:
305
+ // Write side: mqtt duplex.write → wsStream.write → WebSocket (send to FB)
306
+ // Read side: WebSocket msg → wsStream readable → patcher (fix FB header bits) → duplex.push mqtt reads
307
+ function buildStream() {
308
+ var Duplex = require('stream').Duplex;
309
+ var ws = new WebSocket(host, wsOptions);
310
+ ws.on('error', function () { }); // suppress unhandled ws errors
311
+
312
+ var wsStream = WebSocket.createWebSocketStream(ws, { objectMode: false });
313
+ var patcher = createMqttPatchStream();
314
+
315
+ // Wire: wsStream readable → patcher → push into duplex
316
+ wsStream.pipe(patcher);
317
+
318
+ var duplex = new Duplex({
319
+ read: function () { },
320
+ write: function (chunk, enc, cb) {
321
+ wsStream.write(chunk, enc, cb);
322
+ },
323
+ final: function (cb) {
324
+ wsStream.end(cb);
325
+ },
326
+ destroy: function (err, cb) {
327
+ try { wsStream.destroy(err); } catch (_) { }
328
+ cb(err);
329
+ }
330
+ });
331
+
332
+ patcher.on('data', function (data) {
333
+ if (!duplex.destroyed) duplex.push(data);
334
+ });
335
+ patcher.on('end', function () {
336
+ if (!duplex.destroyed) duplex.push(null);
337
+ });
338
+ patcher.on('error', function (e) {
339
+ if (!duplex.destroyed) duplex.destroy(e);
340
+ });
341
+ wsStream.on('error', function (e) {
342
+ if (!duplex.destroyed) duplex.destroy(e);
343
+ });
344
+
345
+ return duplex;
99
346
  }
100
347
 
101
- ctx.mqttClient = new mqtt.Client(_ => websocket(host, options.wsOptions), options);
348
+ startMqttSpinner(ctx.region);
102
349
 
350
+ ctx.mqttClient = new mqtt.MqttClient(buildStream, mqttOptions);
103
351
  global.mqttClient = ctx.mqttClient;
104
352
 
353
+ var mqttClient = ctx.mqttClient;
354
+
105
355
  mqttClient.on('error', function (err) {
356
+ stopMqttSpinner();
106
357
  log.error("listenMqtt", err);
107
358
  mqttClient.end();
108
359
  if (ctx.globalOptions.autoReconnect) getSeqID();
109
360
  else globalCallback({ type: "stop_listen", error: "Connection refused: Server unavailable" }, null);
110
361
  });
111
362
 
363
+ mqttClient.on('close', function () { });
364
+ mqttClient.on('offline', function () { });
365
+ mqttClient.on('reconnect', function () { });
366
+
112
367
  mqttClient.on('connect', function () {
113
- topics.forEach(topicsub => mqttClient.subscribe(topicsub));
114
-
115
- // Display connection success message with branding and loading animation
116
- const messages = [
117
- '\n✅ ST-FCA MQTT Connected',
118
- `📍 Region: ${ctx.region || 'PNB'}`,
119
- `🔄 Auto-reconnect: ${ctx.globalOptions.autoReconnect ? 'Enabled' : 'Disabled'}${ctx.globalOptions.autoReconnect ? ' (reconnects every 3s on disconnect)' : ''}`,
120
- `⏱️ MQTT Restart Interval: ${ctx.globalOptions.restartListenMqtt?.enable ? `${ctx.globalOptions.restartListenMqtt.timeRestart / 1000}s` : 'Disabled'}`,
121
- '🎨 Maintained & Enhanced by ST | Sheikh Tamim\n'
122
- ];
123
-
124
- let index = 0;
125
- const displayMessages = () => {
126
- if (index < messages.length) {
127
- const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
128
- let frameIndex = 0;
129
-
130
- const loadingInterval = setInterval(() => {
131
- process.stdout.write(`\r${frames[frameIndex]} Loading...`);
132
- frameIndex = (frameIndex + 1) % frames.length;
133
- }, 80);
134
-
135
- setTimeout(() => {
136
- clearInterval(loadingInterval);
137
- process.stdout.write('\r' + ' '.repeat(20) + '\r');
138
- console.log(messages[index]);
139
- index++;
140
- displayMessages();
141
- }, 500);
142
- }
143
- };
368
+ topics.forEach(function (topic) { mqttClient.subscribe(topic); });
144
369
 
145
- displayMessages();
370
+ printMqttBanner(ctx.region, ctx.globalOptions.autoReconnect);
146
371
 
147
372
  var topic;
148
373
  var queue = {
@@ -157,8 +382,7 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
157
382
  topic = "/messenger_sync_get_diffs";
158
383
  queue.last_seq_id = ctx.lastSeqId;
159
384
  queue.sync_token = ctx.syncToken;
160
- }
161
- else {
385
+ } else {
162
386
  topic = "/messenger_sync_create_queue";
163
387
  queue.initial_titan_sequence_id = ctx.lastSeqId;
164
388
  queue.device_params = null;
@@ -173,23 +397,21 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
173
397
 
174
398
  ctx.tmsWait = function () {
175
399
  clearTimeout(rTimeout);
176
- ctx.globalOptions.emitReady ? globalCallback({
177
- type: "ready",
178
- error: null
179
- }) : "";
400
+ if (ctx.globalOptions.emitReady) globalCallback({ type: "ready", error: null });
180
401
  delete ctx.tmsWait;
181
402
  };
182
403
  });
183
404
 
184
- mqttClient.on('message', function (topic, message, _packet) {
405
+ mqttClient.on('message', function (topic, message) {
406
+ var jsonMessage;
185
407
  try {
186
- var jsonMessage = JSON.parse(message);
187
- }
188
- catch (ex) {
408
+ jsonMessage = JSON.parse(message.toString());
409
+ } catch (ex) {
189
410
  return log.error("listenMqtt", ex);
190
411
  }
412
+
191
413
  if (topic === "/t_ms") {
192
- if (ctx.tmsWait && typeof ctx.tmsWait == "function") ctx.tmsWait();
414
+ if (ctx.tmsWait && typeof ctx.tmsWait === "function") ctx.tmsWait();
193
415
 
194
416
  if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
195
417
  ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
@@ -198,13 +420,11 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
198
420
 
199
421
  if (jsonMessage.lastIssuedSeqId) ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
200
422
 
201
- //If it contains more than 1 delta
202
423
  for (var i in jsonMessage.deltas) {
203
424
  var delta = jsonMessage.deltas[i];
204
425
  parseDelta(defaultFuncs, api, ctx, globalCallback, { "delta": delta });
205
426
  }
206
- }
207
- else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
427
+ } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
208
428
  var typ = {
209
429
  type: "typ",
210
430
  isTyping: !!jsonMessage.state,
@@ -212,17 +432,13 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
212
432
  threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
213
433
  };
214
434
  (function () { globalCallback(null, typ); })();
215
- }
216
- else if (topic === "/orca_presence") {
435
+ } else if (topic === "/orca_presence") {
217
436
  if (!ctx.globalOptions.updatePresence) {
218
437
  for (var i in jsonMessage.list) {
219
438
  var data = jsonMessage.list[i];
220
- var userID = data["u"];
221
-
222
439
  var presence = {
223
440
  type: "presence",
224
- userID: userID.toString(),
225
- //Convert to ms
441
+ userID: data["u"].toString(),
226
442
  timestamp: data["l"] * 1000,
227
443
  statuses: data["p"]
228
444
  };
@@ -230,57 +446,43 @@ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
230
446
  }
231
447
  }
232
448
  }
233
-
234
449
  });
235
450
 
236
451
  mqttClient.on('close', function () { });
237
452
  }
238
453
 
239
- function attachImgbbUrlToAttachment(api, attachment) {
240
- if (!api || !api.uploadImageToImgbb || !attachment || attachment.type !== "photo" || !attachment.url) return;
241
- api.uploadImageToImgbb(attachment.url).then((result) => {
242
- if (result && result.data) {
243
- attachment.imgbbUrl = result.data.url || result.data.display_url || (result.data.image && result.data.image.url);
244
- }
245
- }).catch(() => { });
454
+ function attachImageUrlToAttachment(api, attachment) {
455
+ if (!attachment || attachment.type !== "photo" || !attachment.url) return;
456
+ if (api && api._imgUpload) {
457
+ api._imgUpload(attachment.url).then(function (url) {
458
+ if (url) attachment.imgUrl = url;
459
+ }).catch(function () { });
460
+ }
246
461
  }
247
462
 
248
463
  function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
249
464
  if (v.delta.class == "NewMessage") {
250
- //Not tested for pages
251
465
  if (ctx.globalOptions.pageID && ctx.globalOptions.pageID != v.queue) return;
252
466
 
253
467
  (function resolveAttachmentUrl(i) {
254
468
  if (i == (v.delta.attachments || []).length) {
255
- let fmtMsg;
469
+ var fmtMsg;
256
470
  try {
257
471
  fmtMsg = utils.formatDeltaMessage(v);
258
- // Detect if it's a DM or group thread - enhanced detection
259
- const otherUserFbId = v.delta.messageMetadata.threadKey.otherUserFbId;
260
- const threadFbId = v.delta.messageMetadata.threadKey.threadFbId;
261
-
262
- // A thread is a DM if it has otherUserFbId and no threadFbId
472
+ var otherUserFbId = v.delta.messageMetadata.threadKey.otherUserFbId;
473
+ var threadFbId = v.delta.messageMetadata.threadKey.threadFbId;
263
474
  fmtMsg.isSingleUser = !!otherUserFbId && !threadFbId;
264
475
  fmtMsg.isGroup = !!threadFbId;
265
-
266
- // Store thread type in context for sendMessage to use
267
476
  if (!ctx.threadTypes) ctx.threadTypes = {};
268
477
  ctx.threadTypes[fmtMsg.threadID] = fmtMsg.isSingleUser ? 'dm' : 'group';
269
478
  if (fmtMsg.attachments && Array.isArray(fmtMsg.attachments)) {
270
- fmtMsg.attachments.forEach(att => attachImgbbUrlToAttachment(api, att));
479
+ fmtMsg.attachments.forEach(function (att) { attachImageUrlToAttachment(api, att); });
271
480
  }
272
481
  } catch (err) {
273
- return globalCallback({
274
- error: "Problem parsing message object.",
275
- detail: err,
276
- res: v,
277
- type: "parse_error"
278
- });
482
+ return globalCallback({ error: "Problem parsing message object.", detail: err, res: v, type: "parse_error" });
279
483
  }
280
- if (fmtMsg) {
281
- if (ctx.globalOptions.autoMarkDelivery) {
282
- markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
283
- }
484
+ if (fmtMsg && ctx.globalOptions.autoMarkDelivery) {
485
+ markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
284
486
  }
285
487
  return !ctx.globalOptions.selfListen &&
286
488
  (fmtMsg.senderID === ctx.i_userID || fmtMsg.senderID === ctx.userID) ?
@@ -288,16 +490,10 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
288
490
  (function () { globalCallback(null, fmtMsg); })();
289
491
  } else {
290
492
  if (v.delta.attachments[i].mercury.attach_type == "photo") {
291
- api.resolvePhotoUrl(
292
- v.delta.attachments[i].fbid,
293
- (err, url) => {
294
- if (!err)
295
- v.delta.attachments[
296
- i
297
- ].mercury.metadata.url = url;
298
- return resolveAttachmentUrl(i + 1);
299
- }
300
- );
493
+ api.resolvePhotoUrl(v.delta.attachments[i].fbid, function (err, url) {
494
+ if (!err) v.delta.attachments[i].mercury.metadata.url = url;
495
+ return resolveAttachmentUrl(i + 1);
496
+ });
301
497
  } else {
302
498
  return resolveAttachmentUrl(i + 1);
303
499
  }
@@ -321,8 +517,7 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
321
517
  userID: delta.deltaMessageReaction.userId.toString()
322
518
  });
323
519
  })();
324
- }
325
- else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
520
+ } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
326
521
  (function () {
327
522
  globalCallback(null, {
328
523
  type: "message_unsend",
@@ -333,21 +528,17 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
333
528
  timestamp: delta.deltaRecallMessageData.timestamp
334
529
  });
335
530
  })();
336
- }
337
- else if (delta.deltaMessageReply) {
338
- //Mention block - #1
531
+ } else if (delta.deltaMessageReply) {
339
532
  var mdata = delta.deltaMessageReply.message === undefined ? [] :
340
533
  delta.deltaMessageReply.message.data === undefined ? [] :
341
534
  delta.deltaMessageReply.message.data.prng === undefined ? [] :
342
535
  JSON.parse(delta.deltaMessageReply.message.data.prng);
343
- var m_id = mdata.map(u => u.i);
344
- var m_offset = mdata.map(u => u.o);
345
- var m_length = mdata.map(u => u.l);
346
-
536
+ var m_id = mdata.map(function (u) { return u.i; });
537
+ var m_offset = mdata.map(function (u) { return u.o; });
538
+ var m_length = mdata.map(function (u) { return u.l; });
347
539
  var mentions = {};
348
-
349
540
  for (var i = 0; i < m_id.length; i++) mentions[m_id[i]] = (delta.deltaMessageReply.message.body || "").substring(m_offset[i], m_offset[i] + m_length[i]);
350
- //Mention block - 1#
541
+
351
542
  var callbackToReturn = {
352
543
  type: "message_reply",
353
544
  threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey.otherUserFbId).toString(),
@@ -357,16 +548,10 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
357
548
  var mercury = JSON.parse(att.mercuryJSON);
358
549
  Object.assign(att, mercury);
359
550
  return att;
360
- }).map(att => {
551
+ }).map(function (att) {
361
552
  var x;
362
- try {
363
- x = utils._formatAttachment(att);
364
- }
365
- catch (ex) {
366
- x = att;
367
- x.error = ex;
368
- x.type = "unknown";
369
- }
553
+ try { x = utils._formatAttachment(att); }
554
+ catch (ex) { x = att; x.error = ex; x.type = "unknown"; }
370
555
  return x;
371
556
  }),
372
557
  args: (delta.deltaMessageReply.message.body || "").trim().split(/\s+/),
@@ -374,26 +559,24 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
374
559
  isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
375
560
  mentions: mentions,
376
561
  timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
377
- participantIDs: (delta.deltaMessageReply.message.messageMetadata.cid.canonicalParticipantFbids || delta.deltaMessageReply.message.participants || []).map(e => e.toString())
562
+ participantIDs: (delta.deltaMessageReply.message.messageMetadata.cid.canonicalParticipantFbids || delta.deltaMessageReply.message.participants || []).map(function (e) { return e.toString(); })
378
563
  };
564
+
379
565
  if (callbackToReturn.attachments && Array.isArray(callbackToReturn.attachments)) {
380
- callbackToReturn.attachments.forEach(att => attachImgbbUrlToAttachment(api, att));
566
+ callbackToReturn.attachments.forEach(function (att) { attachImageUrlToAttachment(api, att); });
381
567
  }
382
568
 
383
569
  if (delta.deltaMessageReply.repliedToMessage) {
384
- //Mention block - #2
385
570
  mdata = delta.deltaMessageReply.repliedToMessage === undefined ? [] :
386
571
  delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
387
572
  delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
388
573
  JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
389
- m_id = mdata.map(u => u.i);
390
- m_offset = mdata.map(u => u.o);
391
- m_length = mdata.map(u => u.l);
392
-
574
+ m_id = mdata.map(function (u) { return u.i; });
575
+ m_offset = mdata.map(function (u) { return u.o; });
576
+ m_length = mdata.map(function (u) { return u.l; });
393
577
  var rmentions = {};
394
-
395
578
  for (var i = 0; i < m_id.length; i++) rmentions[m_id[i]] = (delta.deltaMessageReply.repliedToMessage.body || "").substring(m_offset[i], m_offset[i] + m_length[i]);
396
- //Mention block - 2#
579
+
397
580
  callbackToReturn.messageReply = {
398
581
  threadID: (delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.otherUserFbId).toString(),
399
582
  messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
@@ -402,17 +585,11 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
402
585
  var mercury = JSON.parse(att.mercuryJSON);
403
586
  Object.assign(att, mercury);
404
587
  return att;
405
- }).map(att => {
588
+ }).map(function (att) {
406
589
  var x;
407
- try {
408
- x = utils._formatAttachment(att);
409
- }
410
- catch (ex) {
411
- x = att;
412
- x.error = ex;
413
- x.type = "unknown";
414
- }
415
- attachImgbbUrlToAttachment(api, x);
590
+ try { x = utils._formatAttachment(att); }
591
+ catch (ex) { x = att; x.error = ex; x.type = "unknown"; }
592
+ attachImageUrlToAttachment(api, x);
416
593
  return x;
417
594
  }),
418
595
  args: (delta.deltaMessageReply.repliedToMessage.body || "").trim().split(/\s+/),
@@ -421,14 +598,12 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
421
598
  mentions: rmentions,
422
599
  timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp
423
600
  };
424
- }
425
- else if (delta.deltaMessageReply.replyToMessageId) {
601
+ } else if (delta.deltaMessageReply.replyToMessageId) {
426
602
  return defaultFuncs
427
603
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
428
604
  "av": ctx.globalOptions.pageID,
429
605
  "queries": JSON.stringify({
430
606
  "o0": {
431
- //Using the same doc_id as forcedFetch
432
607
  "doc_id": "2848441488556444",
433
608
  "query_params": {
434
609
  "thread_and_message_id": {
@@ -440,28 +615,21 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
440
615
  })
441
616
  })
442
617
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
443
- .then((resData) => {
618
+ .then(function (resData) {
444
619
  if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
445
620
  if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
446
621
  var fetchData = resData[0].o0.data.message;
447
622
  var mobj = {};
448
623
  for (var n in fetchData.message.ranges) mobj[fetchData.message.ranges[n].entity.id] = (fetchData.message.text || "").substr(fetchData.message.ranges[n].offset, fetchData.message.ranges[n].length);
449
-
450
624
  callbackToReturn.messageReply = {
451
625
  threadID: callbackToReturn.threadID,
452
626
  messageID: fetchData.message_id,
453
627
  senderID: fetchData.message_sender.id.toString(),
454
- attachments: fetchData.message.blob_attachment.map(att => {
628
+ attachments: fetchData.message.blob_attachment.map(function (att) {
455
629
  var x;
456
- try {
457
- x = utils._formatAttachment({ blob_attachment: att });
458
- }
459
- catch (ex) {
460
- x = att;
461
- x.error = ex;
462
- x.type = "unknown";
463
- }
464
- attachImgbbUrlToAttachment(api, x);
630
+ try { x = utils._formatAttachment({ blob_attachment: att }); }
631
+ catch (ex) { x = att; x.error = ex; x.type = "unknown"; }
632
+ attachImageUrlToAttachment(api, x);
465
633
  return x;
466
634
  }),
467
635
  args: (fetchData.message.text || "").trim().split(/\s+/) || [],
@@ -471,16 +639,16 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
471
639
  timestamp: parseInt(fetchData.timestamp_precise)
472
640
  };
473
641
  })
474
- .catch(err => log.error("forcedFetch", err))
642
+ .catch(function (err) { log.error("forcedFetch", err); })
475
643
  .finally(function () {
476
644
  if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
477
645
  !ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID ? undefined : (function () { globalCallback(null, callbackToReturn); })();
478
646
  });
647
+ } else {
648
+ callbackToReturn.delta = delta;
479
649
  }
480
- else callbackToReturn.delta = delta;
481
650
 
482
651
  if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
483
-
484
652
  return !ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID ? undefined : (function () { globalCallback(null, callbackToReturn); })();
485
653
  }
486
654
  }
@@ -489,22 +657,17 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
489
657
  }
490
658
 
491
659
  if (v.delta.class !== "NewMessage" && !ctx.globalOptions.listenEvents) return;
660
+
492
661
  switch (v.delta.class) {
493
662
  case "JoinableMode": {
494
- let fmtMsg;
495
- try {
496
- fmtMsg = utils.formatDeltaEvent(v.delta);
497
- } catch (err) {
498
- return globalCallback({
499
- error: "Lỗi gòi!!",
500
- detail: err,
501
- res: v.delta,
502
- type: "parse_error"
503
- });
663
+ var fmtMsg;
664
+ try { fmtMsg = utils.formatDeltaEvent(v.delta); }
665
+ catch (err) {
666
+ return globalCallback({ error: "Problem parsing message object.", detail: err, res: v.delta, type: "parse_error" });
504
667
  }
505
668
  return globalCallback(null, fmtMsg);
506
669
  }
507
- case "AdminTextMessage":
670
+ case "AdminTextMessage": {
508
671
  switch (v.delta.type) {
509
672
  case 'confirm_friend_request':
510
673
  case 'shared_album_delete':
@@ -521,58 +684,44 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
521
684
  case "magic_words":
522
685
  case "change_thread_approval_mode":
523
686
  case "messenger_call_log":
524
- case "participant_joined_group_call":
687
+ case "participant_joined_group_call": {
525
688
  var fmtMsg;
526
- try {
527
- fmtMsg = utils.formatDeltaEvent(v.delta);
528
- }
689
+ try { fmtMsg = utils.formatDeltaEvent(v.delta); }
529
690
  catch (err) {
530
- return globalCallback({
531
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
532
- detail: err,
533
- res: v.delta,
534
- type: "parse_error"
535
- });
691
+ return globalCallback({ error: "Problem parsing message object.", detail: err, res: v.delta, type: "parse_error" });
536
692
  }
537
693
  return (function () { globalCallback(null, fmtMsg); })();
538
- default:
539
- // console.log(v.delta)
540
- return;
694
+ }
695
+ default: return;
541
696
  }
542
- //For group images
543
- case "ForcedFetch":
697
+ }
698
+ case "ForcedFetch": {
544
699
  if (!v.delta.threadKey) return;
545
700
  var mid = v.delta.messageId;
546
701
  var tid = v.delta.threadKey.threadFbId;
547
702
  if (mid && tid) {
548
- const form = {
703
+ var fetchForm = {
549
704
  "av": ctx.globalOptions.pageID,
550
705
  "queries": JSON.stringify({
551
706
  "o0": {
552
- //This doc_id is valid as of March 25, 2020
553
707
  "doc_id": "2848441488556444",
554
708
  "query_params": {
555
709
  "thread_and_message_id": {
556
710
  "thread_id": tid.toString(),
557
- "message_id": mid,
711
+ "message_id": mid
558
712
  }
559
713
  }
560
714
  }
561
715
  })
562
716
  };
563
-
564
717
  defaultFuncs
565
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
718
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, fetchForm)
566
719
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
567
- .then((resData) => {
720
+ .then(function (resData) {
568
721
  if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
569
-
570
722
  if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
571
-
572
723
  var fetchData = resData[0].o0.data.message;
573
-
574
724
  if (utils.getType(fetchData) == "Object") {
575
- log.info("forcedFetch", fetchData);
576
725
  switch (fetchData.__typename) {
577
726
  case "ThreadImageMessage":
578
727
  (!ctx.globalOptions.selfListen && fetchData.message_sender.id.toString() === ctx.userID) ||
@@ -593,35 +742,6 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
593
742
  })();
594
743
  break;
595
744
  case "UserMessage":
596
- log.info("ff-Return", {
597
- type: "message",
598
- senderID: utils.formatID(fetchData.message_sender.id),
599
- body: fetchData.message.text || "",
600
- threadID: utils.formatID(tid.toString()),
601
- messageID: fetchData.message_id,
602
- attachments: [{
603
- type: "share",
604
- ID: fetchData.extensible_attachment.legacy_attachment_id,
605
- url: fetchData.extensible_attachment.story_attachment.url,
606
-
607
- title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
608
- description: fetchData.extensible_attachment.story_attachment.description.text,
609
- source: fetchData.extensible_attachment.story_attachment.source,
610
-
611
- image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
612
- width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
613
- height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
614
- playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
615
- duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
616
-
617
- subattachments: fetchData.extensible_attachment.subattachments,
618
- properties: fetchData.extensible_attachment.story_attachment.properties,
619
- }],
620
- mentions: {},
621
- timestamp: parseInt(fetchData.timestamp_precise),
622
- participantIDs: (fetchData.participants || (fetchData.messageMetadata ? fetchData.messageMetadata.cid ? fetchData.messageMetadata.cid.canonicalParticipantFbids : fetchData.messageMetadata.participantIds : []) || []),
623
- isGroup: (fetchData.message_sender.id != tid.toString())
624
- });
625
745
  globalCallback(null, {
626
746
  type: "message",
627
747
  senderID: utils.formatID(fetchData.message_sender.id),
@@ -632,178 +752,64 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
632
752
  type: "share",
633
753
  ID: fetchData.extensible_attachment.legacy_attachment_id,
634
754
  url: fetchData.extensible_attachment.story_attachment.url,
635
-
636
755
  title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
637
756
  description: fetchData.extensible_attachment.story_attachment.description.text,
638
757
  source: fetchData.extensible_attachment.story_attachment.source,
639
-
640
758
  image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
641
759
  width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
642
760
  height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
643
761
  playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
644
762
  duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
645
-
646
763
  subattachments: fetchData.extensible_attachment.subattachments,
647
764
  properties: fetchData.extensible_attachment.story_attachment.properties,
648
765
  }],
649
766
  mentions: {},
650
767
  timestamp: parseInt(fetchData.timestamp_precise),
651
- participantIDs: (fetchData.participants || (fetchData.messageMetadata ? fetchData.messageMetadata.cid ? fetchData.messageMetadata.cid.canonicalParticipantFbids : fetchData.messageMetadata.participantIds : []) || []),
652
768
  isGroup: (fetchData.message_sender.id != tid.toString())
653
769
  });
770
+ break;
654
771
  }
655
- }
656
- else log.error("forcedFetch", fetchData);
772
+ } else log.error("forcedFetch", fetchData);
657
773
  })
658
- .catch((err) => log.error("forcedFetch", err));
774
+ .catch(function (err) { log.error("forcedFetch", err); });
659
775
  }
660
776
  break;
777
+ }
661
778
  case "ThreadName":
662
779
  case "ParticipantsAddedToGroupThread":
663
- case "ParticipantLeftGroupThread":
780
+ case "ParticipantLeftGroupThread": {
664
781
  var formattedEvent;
665
- try {
666
- formattedEvent = utils.formatDeltaEvent(v.delta);
667
- }
782
+ try { formattedEvent = utils.formatDeltaEvent(v.delta); }
668
783
  catch (err) {
669
- return globalCallback({
670
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
671
- detail: err,
672
- res: v.delta,
673
- type: "parse_error"
674
- });
784
+ return globalCallback({ error: "Problem parsing message object.", detail: err, res: v.delta, type: "parse_error" });
675
785
  }
676
786
  return (!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID) || !ctx.loggedIn ? undefined : (function () { globalCallback(null, formattedEvent); })();
787
+ }
677
788
  }
678
789
  }
679
790
 
680
791
  function markDelivery(ctx, api, threadID, messageID) {
681
792
  if (threadID && messageID) {
682
- api.markAsDelivered(threadID, messageID, (err) => {
793
+ api.markAsDelivered(threadID, messageID, function (err) {
683
794
  if (err) log.error("markAsDelivered", err);
684
- else {
685
- if (ctx.globalOptions.autoMarkRead) {
686
- api.markAsRead(threadID, (err) => {
687
- if (err) log.error("markAsDelivered", err);
688
- });
689
- }
795
+ else if (ctx.globalOptions.autoMarkRead) {
796
+ api.markAsRead(threadID, function (err) {
797
+ if (err) log.error("markAsDelivered", err);
798
+ });
690
799
  }
691
800
  });
692
801
  }
693
802
  }
694
803
 
695
804
  module.exports = function (defaultFuncs, api, ctx) {
696
- let globalCallback = identity;
697
- // function getSeqID() {
698
- // ctx.t_mqttCalled = false;
699
- // async function attemptRequest(retries = 3) {
700
- // try {
701
- // if (!ctx.fb_dtsg) {
702
- // const dtsg = await api.getFreshDtsg();
703
- // if (!dtsg) {
704
- // if (retries > 0) {
705
- // logger.Warning("Failed to get fb_dtsg, retrying...");
706
- // await utils.sleep(2000); // Longer delay for token retry
707
- // return attemptRequest(retries - 1);
708
- // }
709
- // throw { error: "Could not obtain fb_dtsg after multiple attempts" };
710
- // }
711
- // ctx.fb_dtsg = dtsg;
712
- // }
713
-
714
- // const form = {
715
- // av: ctx.userID,
716
- // fb_dtsg: ctx.fb_dtsg,
717
- // queries: JSON.stringify({
718
- // o0: {
719
- // doc_id: '3336396659757871',
720
- // query_params: {
721
- // limit: 1,
722
- // before: null,
723
- // tags: ['INBOX'],
724
- // includeDeliveryReceipts: false,
725
- // includeSeqID: true
726
- // }
727
- // }
728
- // }),
729
- // __user: ctx.userID,
730
- // __a: '1',
731
- // __req: '8',
732
- // __hs: '19577.HYP:comet_pkg.2.1..2.1',
733
- // dpr: '1',
734
- // fb_api_caller_class: 'RelayModern',
735
- // fb_api_req_friendly_name: 'MessengerGraphQLThreadlistFetcher'
736
- // };
737
-
738
- // const headers = {
739
- // 'Content-Type': 'application/x-www-form-urlencoded',
740
- // 'Referer': 'https://www.facebook.com/',
741
- // 'Origin': 'https://www.facebook.com',
742
- // 'sec-fetch-site': 'same-origin',
743
- // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
744
- // 'Cookie': ctx.jar.getCookieString('https://www.facebook.com'),
745
- // 'accept': '*/*',
746
- // 'accept-encoding': 'gzip, deflate, br'
747
- // };
748
-
749
- // const resData = await defaultFuncs
750
- // .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form, { headers })
751
- // .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
752
-
753
- // if (debugSeq) {
754
- // console.log('GraphQL SeqID Response:', JSON.stringify(resData, null, 2));
755
- // }
756
-
757
- // if (resData.error === 1357004 || resData.error === 1357001) {
758
- // if (retries > 0) {
759
- // logger.Warning("Session error, refreshing token and retrying...");
760
- // ctx.fb_dtsg = null; // Force new token
761
- // await utils.sleep(2000);
762
- // return attemptRequest(retries - 1);
763
- // }
764
- // throw { error: "Session refresh failed after retries" };
765
- // }
766
-
767
- // if (!Array.isArray(resData)) {
768
- // throw { error: "Invalid response format", res: resData };
769
- // }
770
-
771
- // const seqID = resData[0]?.o0?.data?.viewer?.message_threads?.sync_sequence_id;
772
- // if (!seqID) {
773
- // throw { error: "Missing sync_sequence_id", res: resData };
774
- // }
775
-
776
- // ctx.lastSeqId = seqID;
777
- // if (debugSeq) {
778
- // console.log('Got SeqID:', ctx.lastSeqId);
779
- // }
780
-
781
- // return listenMqtt(defaultFuncs, api, ctx, globalCallback);
782
-
783
- // } catch (err) {
784
- // if (retries > 0) {
785
- // console.log("Request failed, retrying...");
786
-
787
- // return attemptRequest(retries - 1);
788
- // }
789
- // throw err;
790
- // }
791
- // }
792
-
793
- // return attemptRequest()
794
- // .catch((err) => {
795
- // log.error("getSeqId", err);
796
- // if (utils.getType(err) == "Object" && err.error === "Not logged in") ctx.loggedIn = false;
797
- // return globalCallback(err);
798
- // });
799
- // }
805
+ var globalCallback = identity;
800
806
 
801
807
  getSeqID = function getSeqID() {
802
808
  ctx.t_mqttCalled = false;
803
809
  defaultFuncs
804
810
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
805
811
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
806
- .then((resData) => {
812
+ .then(function (resData) {
807
813
  if (utils.getType(resData) != "Array") throw { error: "Not logged in", res: resData };
808
814
  if (resData && resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
809
815
  if (resData[resData.length - 1].successful_results === 0) throw { error: "getSeqId: there was no successful_results", res: resData };
@@ -812,7 +818,7 @@ module.exports = function (defaultFuncs, api, ctx) {
812
818
  listenMqtt(defaultFuncs, api, ctx, globalCallback);
813
819
  } else throw { error: "getSeqId: no sync_sequence_id found.", res: resData };
814
820
  })
815
- .catch((err) => {
821
+ .catch(function (err) {
816
822
  log.error("getSeqId", err);
817
823
  if (utils.getType(err) == "Object" && err.error === "Not logged in") ctx.loggedIn = false;
818
824
  return globalCallback(err);
@@ -822,8 +828,7 @@ module.exports = function (defaultFuncs, api, ctx) {
822
828
  return function (callback) {
823
829
  class MessageEmitter extends EventEmitter {
824
830
  stopListening(callback) {
825
-
826
- callback = callback || (() => { });
831
+ callback = callback || (function () { });
827
832
  globalCallback = identity;
828
833
  if (ctx.mqttClient) {
829
834
  ctx.mqttClient.unsubscribe("/webrtc");
@@ -838,23 +843,19 @@ module.exports = function (defaultFuncs, api, ctx) {
838
843
  }
839
844
 
840
845
  async stopListeningAsync() {
841
- return new Promise((resolve) => {
846
+ return new Promise(function (resolve) {
842
847
  this.stopListening(resolve);
843
- });
848
+ }.bind(this));
844
849
  }
845
850
  }
846
851
 
847
- const msgEmitter = new MessageEmitter();
852
+ var msgEmitter = new MessageEmitter();
848
853
  globalCallback = (callback || function (error, message) {
849
- if (error) {
850
- return msgEmitter.emit("error", error);
851
- }
854
+ if (error) return msgEmitter.emit("error", error);
852
855
  msgEmitter.emit("message", message);
853
856
  });
854
857
 
855
- // Reset some stuff
856
- if (!ctx.firstListen)
857
- ctx.lastSeqId = null;
858
+ if (!ctx.firstListen) ctx.lastSeqId = null;
858
859
  ctx.syncToken = undefined;
859
860
  ctx.t_mqttCalled = false;
860
861
 
@@ -880,8 +881,8 @@ module.exports = function (defaultFuncs, api, ctx) {
880
881
  listenMqtt(defaultFuncs, api, ctx, globalCallback);
881
882
  }
882
883
 
883
- api.stopListening = msgEmitter.stopListening;
884
- api.stopListeningAsync = msgEmitter.stopListeningAsync;
884
+ api.stopListening = msgEmitter.stopListening.bind(msgEmitter);
885
+ api.stopListeningAsync = msgEmitter.stopListeningAsync.bind(msgEmitter);
885
886
  return msgEmitter;
886
887
  };
887
- };
888
+ };