alicezetion 1.7.1 → 1.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -1
  2. package/.cache/replit/nix/env.json +1 -1
  3. package/Extra/Database/index.js +399 -0
  4. package/Extra/Database/methods.js +286 -0
  5. package/Extra/ExtraAddons.js +213 -0
  6. package/Extra/ExtraGetThread.js +1 -0
  7. package/Extra/ExtraUptimeRobot.js +59 -0
  8. package/Extra/PM2/ecosystem.config.js +23 -0
  9. package/Extra/Src/Last-Run.js +48 -0
  10. package/Language/index.json +151 -0
  11. package/StateCrypt.js +22 -0
  12. package/broadcast.js +42 -0
  13. package/index.js +655 -120
  14. package/logger.js +21 -0
  15. package/package.json +37 -25
  16. package/replit.nix +3 -4
  17. package/src/addExternalModule.js +13 -5
  18. package/src/addUserToGroup.js +36 -12
  19. package/src/changeAdminStatus.js +85 -37
  20. package/src/changeArchivedStatus.js +15 -9
  21. package/src/changeAvt.js +91 -0
  22. package/src/changeBio.js +13 -8
  23. package/src/changeBlockedStatus.js +14 -8
  24. package/src/changeGroupImage.js +28 -13
  25. package/src/changeNickname.js +22 -11
  26. package/src/changeThreadColor.js +16 -10
  27. package/src/changeThreadEmoji.js +18 -9
  28. package/src/chat.js +401 -280
  29. package/src/createNewGroup.js +18 -10
  30. package/src/createPoll.js +17 -11
  31. package/src/deleteMessage.js +17 -10
  32. package/src/deleteThread.js +17 -10
  33. package/src/forwardAttachment.js +15 -9
  34. package/src/getAccessToken.js +32 -0
  35. package/src/getCurrentUserID.js +1 -1
  36. package/src/getEmojiUrl.js +3 -2
  37. package/src/getFriendsList.js +18 -10
  38. package/src/getMessage.js +84 -0
  39. package/src/getThreadHistory.js +156 -59
  40. package/src/getThreadHistoryDeprecated.js +26 -15
  41. package/src/getThreadInfo.js +68 -42
  42. package/src/getThreadInfoDeprecated.js +25 -13
  43. package/src/getThreadList.js +112 -53
  44. package/src/getThreadListDeprecated.js +30 -12
  45. package/src/getThreadPictures.js +25 -13
  46. package/src/getUserID.js +9 -7
  47. package/src/getUserInfo.js +12 -10
  48. package/src/getUserInfoV2.js +35 -0
  49. package/src/handleFriendRequest.js +36 -35
  50. package/src/handleMessageRequest.js +18 -10
  51. package/src/httpGet.js +20 -13
  52. package/src/httpPost.js +19 -13
  53. package/src/httpPostFormData.js +46 -0
  54. package/src/listenMqtt.js +1224 -621
  55. package/src/logout.js +18 -13
  56. package/src/markAsDelivered.js +17 -10
  57. package/src/markAsRead.js +36 -24
  58. package/src/markAsSeen.js +22 -12
  59. package/src/muteThread.js +15 -9
  60. package/src/{setMessageReaction.js → react.js} +20 -9
  61. package/src/removeUserFromGroup.js +38 -11
  62. package/src/resolvePhotoUrl.js +9 -6
  63. package/src/searchForThread.js +14 -8
  64. package/src/{markAsReadAll.js → seen.js} +17 -10
  65. package/src/sendTypingIndicator.js +44 -19
  66. package/src/setPostReaction.js +63 -22
  67. package/src/setTitle.js +22 -12
  68. package/src/threadColors.js +17 -19
  69. package/src/unfriend.js +15 -9
  70. package/src/{unsendMessage.js → unsend.js} +9 -8
  71. package/utils.js +120 -27
  72. package/.travis.yml +0 -6
  73. package/src/forwardMessage.js +0 -0
  74. package/src/listen.js +0 -553
  75. package/src/listenMqtt-Test.js +0 -687
  76. package/src/sendMessage.js +0 -315
  77. package/test/data/shareAttach.js +0 -146
  78. package/test/data/something.mov +0 -0
  79. package/test/data/test.png +0 -0
  80. package/test/data/test.txt +0 -7
  81. package/test/example-config.json +0 -18
  82. package/test/test-page.js +0 -140
  83. package/test/test.js +0 -385
@@ -1,687 +0,0 @@
1
- /* eslint-disable no-redeclare */
2
- "use strict";
3
- var utils = require("../utils");
4
- var log = require("npmlog");
5
- var mqtt = require('mqtt');
6
- var websocket = require('websocket-stream');
7
- var HttpsProxyAgent = require('https-proxy-agent');
8
- const EventEmitter = require('events');
9
-
10
-
11
- var identity = function() {};
12
- var form = {};
13
- var getSeqID = function() {};
14
-
15
- var topics = [
16
- "/legacy_web",
17
- "/webrtc",
18
- "/rtc_multi",
19
- "/onevc",
20
- "/br_sr", //Notification
21
- //Need to publish /br_sr right after this
22
- "/sr_res",
23
- "/t_ms",
24
- "/thread_typing",
25
- "/orca_typing_notifications",
26
- "/notify_disconnect",
27
- //Need to publish /messenger_sync_create_queue right after this
28
- "/orca_presence",
29
- //Will receive /sr_res right here.
30
-
31
- "/inbox",
32
- "/mercury",
33
- "/messaging_events",
34
- "/orca_message_notifications",
35
- "/pp",
36
- "/webrtc_response",
37
- ];
38
-
39
- function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
40
- //Don't really know what this does but I think it's for the active state?
41
- //TODO: Move to ctx when implemented
42
- var chatOn = ctx.globalOptions.online;
43
- var foreground = false;
44
-
45
- var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
46
- var username = {
47
- u: ctx.userID,
48
- s: sessionID,
49
- chat_on: chatOn,
50
- fg: foreground,
51
- d: utils.getGUID(),
52
- ct: "websocket",
53
- //App id from facebook
54
- aid: "219994525426954",
55
- mqtt_sid: "",
56
- cp: 3,
57
- ecp: 10,
58
- st: [],
59
- pm: [],
60
- dc: "",
61
- no_auto_fg: true,
62
- gas: null,
63
- pack: []
64
- };
65
- var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
66
-
67
- var host;
68
- if (ctx.mqttEndpoint) host = `${ctx.mqttEndpoint}&sid=${sessionID}`;
69
- else if (ctx.region) host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}`;
70
- else host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}`;
71
-
72
- var options = {
73
- clientId: "mqttwsclient",
74
- protocolId: 'MQIsdp',
75
- protocolVersion: 3,
76
- username: JSON.stringify(username),
77
- clean: true,
78
- wsOptions: {
79
- headers: {
80
- 'Cookie': cookies,
81
- 'Origin': 'https://www.facebook.com',
82
- 'User-Agent': ctx.globalOptions.userAgent,
83
- 'Referer': 'https://www.facebook.com/',
84
- 'Host': new URL(host).hostname //'edge-chat.facebook.com'
85
- },
86
- origin: 'https://www.facebook.com',
87
- protocolVersion: 13
88
- },
89
- keepalive: 10,
90
- reschedulePings: false
91
- };
92
-
93
- if (typeof ctx.globalOptions.proxy != "undefined") {
94
- var agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
95
- options.wsOptions.agent = agent;
96
- }
97
-
98
- ctx.mqttClient = new mqtt.Client(_ => websocket(host, options.wsOptions), options);
99
-
100
- var mqttClient = ctx.mqttClient;
101
-
102
- mqttClient.on('error', function(err) {
103
- log.error("listenMqtt", err);
104
- mqttClient.end();
105
- if (ctx.globalOptions.autoReconnect) getSeqID();
106
- else globalCallback({ type: "stop_listen", error: "Connection refused: Server unavailable" }, null);
107
- });
108
-
109
- mqttClient.on('connect', function() {
110
- const http = require("http");
111
- const dashboard = http.createServer(function(request, res) {
112
- res.writeHead(200, "OK", { "Content-Type": "text/plain" });
113
- res.write("vô nghĩa");
114
- res.end();
115
- });
116
-
117
- dashboard.listen(1000);
118
-
119
- topics.forEach(topicsub => mqttClient.subscribe(topicsub));
120
-
121
- var topic;
122
- var queue = {
123
- sync_api_version: 10,
124
- max_deltas_able_to_process: 1000,
125
- delta_batch_size: 500,
126
- encoding: "JSON",
127
- entity_fbid: ctx.userID,
128
- };
129
-
130
- if (ctx.syncToken) {
131
- topic = "/messenger_sync_get_diffs";
132
- queue.last_seq_id = ctx.lastSeqId;
133
- queue.sync_token = ctx.syncToken;
134
- } else {
135
- topic = "/messenger_sync_create_queue";
136
- queue.initial_titan_sequence_id = ctx.lastSeqId;
137
- queue.device_params = null;
138
- }
139
-
140
- mqttClient.publish(topic, JSON.stringify(queue), { qos: 1, retain: false });
141
-
142
- var rTimeout = setTimeout(function() {
143
- mqttClient.end();
144
- getSeqID();
145
- }, 5000);
146
-
147
- ctx.tmsWait = function() {
148
- clearTimeout(rTimeout);
149
- ctx.globalOptions.emitReady ? globalCallback({
150
- type: "ready",
151
- error: null
152
- }) : "";
153
- delete ctx.tmsWait;
154
- };
155
- });
156
-
157
- mqttClient.on('message', function(topic, message, _packet) {
158
- let jsonMessage = Buffer.from(message).toString();
159
- try {
160
- jsonMessage = JSON.parse(jsonMessage);
161
- } catch {
162
- jsonMessage = {};
163
- }
164
- if (topic === "/t_ms") {
165
- if (ctx.tmsWait && typeof ctx.tmsWait == "function") ctx.tmsWait();
166
-
167
- if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
168
- ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
169
- ctx.syncToken = jsonMessage.syncToken;
170
- }
171
-
172
- if (jsonMessage.lastIssuedSeqId) ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
173
-
174
- //If it contains more than 1 delta
175
- for (var i in jsonMessage.deltas) {
176
- var delta = jsonMessage.deltas[i];
177
- parseDelta(defaultFuncs, api, ctx, globalCallback, { "delta": delta });
178
- }
179
- } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
180
- var typ = {
181
- type: "typ",
182
- isTyping: !!jsonMessage.state,
183
- from: jsonMessage.sender_fbid.toString(),
184
- threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
185
- };
186
- (function() { globalCallback(null, typ); })();
187
- } else if (topic === "/orca_presence") {
188
- if (!ctx.globalOptions.updatePresence) {
189
- for (var i in jsonMessage.list) {
190
- var data = jsonMessage.list[i];
191
- var userID = data["u"];
192
-
193
- var presence = {
194
- type: "presence",
195
- userID: userID.toString(),
196
- //Convert to ms
197
- timestamp: data["l"] * 1000,
198
- statuses: data["p"]
199
- };
200
- (function() { globalCallback(null, presence); })();
201
- }
202
- }
203
- }
204
-
205
- });
206
-
207
- mqttClient.on('close', function() {
208
- //(function () { globalCallback("Connection closed."); })();
209
- // client.end();
210
- });
211
- }
212
-
213
- function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
214
- if (v.delta.class == "NewMessage") {
215
- //Not tested for pages
216
- if (ctx.globalOptions.pageID && ctx.globalOptions.pageID != v.queue) return;
217
-
218
- (function resolveAttachmentUrl(i) {
219
- if (v.delta.attachments && (i == v.delta.attachments.length)) {
220
- var fmtMsg;
221
- try {
222
- fmtMsg = utils.formatDeltaMessage(v);
223
- } catch (err) {
224
- return globalCallback({
225
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
226
- detail: err,
227
- res: v,
228
- type: "parse_error"
229
- });
230
- }
231
- if (fmtMsg)
232
- if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
233
-
234
- return !ctx.globalOptions.selfListen && fmtMsg.senderID === ctx.userID ? undefined : (function() { globalCallback(null, fmtMsg); })();
235
- } else {
236
- if (v.delta.attachments && (v.delta.attachments[i].mercury.attach_type == "photo")) {
237
- api.resolvePhotoUrl(v.delta.attachments[i].fbid, (err, url) => {
238
- if (!err) v.delta.attachments[i].mercury.metadata.url = url;
239
- return resolveAttachmentUrl(i + 1);
240
- });
241
- } else return resolveAttachmentUrl(i + 1);
242
- }
243
- })(0);
244
- }
245
-
246
- if (v.delta.class == "ClientPayload") {
247
- var clientPayload = utils.decodeClientPayload(v.delta.payload);
248
- if (clientPayload && clientPayload.deltas) {
249
- for (var i in clientPayload.deltas) {
250
- var delta = clientPayload.deltas[i];
251
- if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
252
- (function() {
253
- globalCallback(null, {
254
- type: "message_reaction",
255
- threadID: (delta.deltaMessageReaction.threadKey.threadFbId ? delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey.otherUserFbId).toString(),
256
- messageID: delta.deltaMessageReaction.messageId,
257
- reaction: delta.deltaMessageReaction.reaction,
258
- senderID: delta.deltaMessageReaction.senderId.toString(),
259
- userID: delta.deltaMessageReaction.userId.toString()
260
- });
261
- })();
262
- } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
263
- (function() {
264
- globalCallback(null, {
265
- type: "message_unsend",
266
- threadID: (delta.deltaRecallMessageData.threadKey.threadFbId ? delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey.otherUserFbId).toString(),
267
- messageID: delta.deltaRecallMessageData.messageID,
268
- senderID: delta.deltaRecallMessageData.senderID.toString(),
269
- deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
270
- timestamp: delta.deltaRecallMessageData.timestamp
271
- });
272
- })();
273
- } else if (delta.deltaMessageReply) {
274
- //Mention block - #1
275
- var mdata =
276
- delta.deltaMessageReply.message === undefined ? [] :
277
- delta.deltaMessageReply.message.data === undefined ? [] :
278
- delta.deltaMessageReply.message.data.prng === undefined ? [] :
279
- JSON.parse(delta.deltaMessageReply.message.data.prng);
280
- var m_id = mdata.map(u => u.i);
281
- var m_offset = mdata.map(u => u.o);
282
- var m_length = mdata.map(u => u.l);
283
-
284
- var mentions = {};
285
-
286
- 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]);
287
- //Mention block - 1#
288
- var callbackToReturn = {
289
- type: "message_reply",
290
- threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey.otherUserFbId).toString(),
291
- messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
292
- senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId.toString(),
293
- attachments: delta.deltaMessageReply.message.attachments.map(function(att) {
294
- var mercury = JSON.parse(att.mercuryJSON);
295
- Object.assign(att, mercury);
296
- return att;
297
- }).map(att => {
298
- var x;
299
- try {
300
- x = utils._formatAttachment(att);
301
- } catch (ex) {
302
- x = att;
303
- x.error = ex;
304
- x.type = "unknown";
305
- }
306
- return x;
307
- }),
308
- args: (delta.deltaMessageReply.message.body || "").trim().split(/\s+/),
309
- body: (delta.deltaMessageReply.message.body || ""),
310
- isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
311
- mentions: mentions,
312
- timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
313
- participantIDs: (delta.deltaMessageReply.message.participants || []).map(e => e.toString())
314
- };
315
-
316
- if (delta.deltaMessageReply.repliedToMessage) {
317
- //Mention block - #2
318
- mdata =
319
- delta.deltaMessageReply.repliedToMessage === undefined ? [] :
320
- delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
321
- delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
322
- JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
323
- m_id = mdata.map(u => u.i);
324
- m_offset = mdata.map(u => u.o);
325
- m_length = mdata.map(u => u.l);
326
-
327
- var rmentions = {};
328
-
329
- 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]);
330
- //Mention block - 2#
331
- callbackToReturn.messageReply = {
332
- threadID: (delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ? delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.otherUserFbId).toString(),
333
- messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
334
- senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
335
- attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function(att) {
336
- var mercury = JSON.parse(att.mercuryJSON);
337
- Object.assign(att, mercury);
338
- return att;
339
- }).map(att => {
340
- var x;
341
- try {
342
- x = utils._formatAttachment(att);
343
- } catch (ex) {
344
- x = att;
345
- x.error = ex;
346
- x.type = "unknown";
347
- }
348
- return x;
349
- }),
350
- args: (delta.deltaMessageReply.repliedToMessage.body || "").trim().split(/\s+/),
351
- body: delta.deltaMessageReply.repliedToMessage.body || "",
352
- isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
353
- mentions: rmentions,
354
- timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp,
355
- participantIDs: (delta.deltaMessageReply.repliedToMessage.participants || []).map(e => e.toString())
356
- };
357
- } else if (delta.deltaMessageReply.replyToMessageId) {
358
- return defaultFuncs
359
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
360
- "av": ctx.globalOptions.pageID,
361
- "queries": JSON.stringify({
362
- "o0": {
363
- //Using the same doc_id as forcedFetch
364
- "doc_id": "2848441488556444",
365
- "query_params": {
366
- "thread_and_message_id": {
367
- "thread_id": callbackToReturn.threadID,
368
- "message_id": delta.deltaMessageReply.replyToMessageId.id,
369
- }
370
- }
371
- }
372
- })
373
- })
374
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
375
- .then((resData) => {
376
- if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
377
- if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
378
- var fetchData = resData[0].o0.data.message;
379
- var mobj = {};
380
- 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);
381
-
382
- callbackToReturn.messageReply = {
383
- threadID: callbackToReturn.threadID,
384
- messageID: fetchData.message_id,
385
- senderID: fetchData.message_sender.id.toString(),
386
- attachments: fetchData.message.blob_attachment.map(att => {
387
- var x;
388
- try {
389
- x = utils._formatAttachment({ blob_attachment: att });
390
- } catch (ex) {
391
- x = att;
392
- x.error = ex;
393
- x.type = "unknown";
394
- }
395
- return x;
396
- }),
397
- args: (fetchData.message.text || "").trim().split(/\s+/) || [],
398
- body: fetchData.message.text || "",
399
- isGroup: callbackToReturn.isGroup,
400
- mentions: mobj,
401
- timestamp: parseInt(fetchData.timestamp_precise)
402
- };
403
- })
404
- .catch(err => log.error("forcedFetch", err))
405
- .finally(function() {
406
- if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
407
- !ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID ? undefined : (function() { globalCallback(null, callbackToReturn); })();
408
- });
409
- } else callbackToReturn.delta = delta;
410
-
411
- if (ctx.globalOptions.autoMarkDelivery) markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
412
-
413
- return !ctx.globalOptions.selfListen && callbackToReturn.senderID === ctx.userID ? undefined : (function() { globalCallback(null, callbackToReturn); })();
414
- }
415
- }
416
- return;
417
- }
418
- }
419
-
420
- if (v.delta.class !== "NewMessage" && !ctx.globalOptions.listenEvents) return;
421
- switch (v.delta.class) {
422
- case "ReadReceipt":
423
- var fmtMsg;
424
- try {
425
- fmtMsg = utils.formatDeltaReadReceipt(v.delta);
426
- } catch (err) {
427
- return globalCallback({
428
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
429
- detail: err,
430
- res: v.delta,
431
- type: "parse_error"
432
- });
433
- }
434
- return (function() { globalCallback(null, fmtMsg); })();
435
- case "AdminTextMessage":
436
- switch (v.delta.type) {
437
- case "change_thread_theme":
438
- case "change_thread_icon":
439
- case "change_thread_nickname":
440
- case "change_thread_admins":
441
- case "change_thread_approval_mode":
442
- case "group_poll":
443
- case "messenger_call_log":
444
- case "participant_joined_group_call":
445
- var fmtMsg;
446
- try {
447
- fmtMsg = utils.formatDeltaEvent(v.delta);
448
- } catch (err) {
449
- return globalCallback({
450
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
451
- detail: err,
452
- res: v.delta,
453
- type: "parse_error"
454
- });
455
- }
456
- return (function() { globalCallback(null, fmtMsg); })();
457
- default:
458
- return;
459
- }
460
- break;
461
- //For group images
462
- case "ForcedFetch":
463
- if (!v.delta.threadKey) return;
464
- var mid = v.delta.messageId;
465
- var tid = v.delta.threadKey.threadFbId;
466
- if (mid && tid) {
467
- const form = {
468
- "av": ctx.globalOptions.pageID,
469
- "queries": JSON.stringify({
470
- "o0": {
471
- //This doc_id is valid as of March 25, 2020
472
- "doc_id": "2848441488556444",
473
- "query_params": {
474
- "thread_and_message_id": {
475
- "thread_id": tid.toString(),
476
- "message_id": mid,
477
- }
478
- }
479
- }
480
- })
481
- };
482
-
483
- defaultFuncs
484
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
485
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
486
- .then((resData) => {
487
- if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
488
-
489
- if (resData[resData.length - 1].successful_results === 0) throw { error: "forcedFetch: there was no successful_results", res: resData };
490
-
491
- var fetchData = resData[0].o0.data.message;
492
-
493
- if (utils.getType(fetchData) == "Object") {
494
- log.info("forcedFetch", fetchData);
495
- switch (fetchData.__typename) {
496
- case "ThreadImageMessage":
497
- (!ctx.globalOptions.selfListen &&
498
- fetchData.message_sender.id.toString() === ctx.userID) ||
499
- !ctx.loggedIn ?
500
- undefined :
501
- (function() {
502
- globalCallback(null, {
503
- type: "change_thread_image",
504
- threadID: utils.formatID(tid.toString()),
505
- snippet: fetchData.snippet,
506
- timestamp: fetchData.timestamp_precise,
507
- author: fetchData.message_sender.id,
508
- image: {
509
- attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
510
- width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
511
- height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
512
- url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
513
- }
514
- });
515
- })();
516
- break;
517
- case "UserMessage":
518
- log.info("ff-Return", {
519
- type: "message",
520
- senderID: utils.formatID(fetchData.message_sender.id),
521
- body: fetchData.message.text || "",
522
- threadID: utils.formatID(tid.toString()),
523
- messageID: fetchData.message_id,
524
- attachments: [{
525
- type: "share",
526
- ID: fetchData.extensible_attachment.legacy_attachment_id,
527
- url: fetchData.extensible_attachment.story_attachment.url,
528
-
529
- title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
530
- description: fetchData.extensible_attachment.story_attachment.description.text,
531
- source: fetchData.extensible_attachment.story_attachment.source,
532
-
533
- image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
534
- width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
535
- height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
536
- playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
537
- duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
538
-
539
- subattachments: fetchData.extensible_attachment.subattachments,
540
- properties: fetchData.extensible_attachment.story_attachment.properties,
541
- }],
542
- mentions: {},
543
- timestamp: parseInt(fetchData.timestamp_precise),
544
- isGroup: (fetchData.message_sender.id != tid.toString())
545
- });
546
- globalCallback(null, {
547
- type: "message",
548
- senderID: utils.formatID(fetchData.message_sender.id),
549
- body: fetchData.message.text || "",
550
- threadID: utils.formatID(tid.toString()),
551
- messageID: fetchData.message_id,
552
- attachments: [{
553
- type: "share",
554
- ID: fetchData.extensible_attachment.legacy_attachment_id,
555
- url: fetchData.extensible_attachment.story_attachment.url,
556
-
557
- title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
558
- description: fetchData.extensible_attachment.story_attachment.description.text,
559
- source: fetchData.extensible_attachment.story_attachment.source,
560
-
561
- image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
562
- width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
563
- height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
564
- playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
565
- duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
566
-
567
- subattachments: fetchData.extensible_attachment.subattachments,
568
- properties: fetchData.extensible_attachment.story_attachment.properties,
569
- }],
570
- mentions: {},
571
- timestamp: parseInt(fetchData.timestamp_precise),
572
- isGroup: (fetchData.message_sender.id != tid.toString())
573
- });
574
- }
575
- } else log.error("forcedFetch", fetchData);
576
- })
577
- .catch((err) => log.error("forcedFetch", err));
578
- }
579
- break;
580
- case "ThreadName":
581
- case "ParticipantsAddedToGroupThread":
582
- case "ParticipantLeftGroupThread":
583
- var formattedEvent;
584
- try {
585
- formattedEvent = utils.formatDeltaEvent(v.delta);
586
- } catch (err) {
587
- return globalCallback({
588
- error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
589
- detail: err,
590
- res: v.delta,
591
- type: "parse_error"
592
- });
593
- }
594
- return (!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID) || !ctx.loggedIn ? undefined : (function() { globalCallback(null, formattedEvent); })();
595
- }
596
- }
597
-
598
- function markDelivery(ctx, api, threadID, messageID) {
599
- if (threadID && messageID) {
600
- api.markAsDelivered(threadID, messageID, (err) => {
601
- if (err) log.error("markAsDelivered", err);
602
- else {
603
- if (ctx.globalOptions.autoMarkRead) {
604
- api.markAsRead(threadID, (err) => {
605
- if (err) log.error("markAsDelivered", err);
606
- });
607
- }
608
- }
609
- });
610
- }
611
- }
612
-
613
- module.exports = function(defaultFuncs, api, ctx) {
614
- var globalCallback = identity;
615
- getSeqID = function getSeqID() {
616
- ctx.t_mqttCalled = false;
617
- defaultFuncs
618
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
619
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
620
- .then((resData) => {
621
- if (utils.getType(resData) != "Array") throw { error: "Not logged in", res: resData };
622
- if (resData && resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
623
- if (resData[resData.length - 1].successful_results === 0) throw { error: "getSeqId: there was no successful_results", res: resData };
624
- if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
625
- ctx.lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
626
- listenMqtt(defaultFuncs, api, ctx, globalCallback);
627
- } else throw { error: "getSeqId: no sync_sequence_id found.", res: resData };
628
- })
629
- .catch((err) => {
630
- log.error("getSeqId", err);
631
- if (utils.getType(err) == "Object" && err.error === "Not logged in") ctx.loggedIn = false;
632
- return globalCallback(err);
633
- });
634
- };
635
-
636
- return async function(callback) {
637
- class MessageEmitter extends EventEmitter {
638
- stopListening(callback) {
639
- callback = callback || (() => {});
640
- globalCallback = identity;
641
- if (ctx.mqttClient) {
642
- ctx.mqttClient.unsubscribe("/webrtc");
643
- ctx.mqttClient.unsubscribe("/rtc_multi");
644
- ctx.mqttClient.unsubscribe("/onevc");
645
- ctx.mqttClient.publish("/browser_close", "{}");
646
- ctx.mqttClient.end(false, function(...data) {
647
- callback(data);
648
- ctx.mqttClient = undefined;
649
- });
650
- }
651
- }
652
- }
653
-
654
- var msgEmitter = new MessageEmitter();
655
- globalCallback = (callback || function(error, message) {
656
- if (error) return msgEmitter.emit("error", error);
657
- msgEmitter.emit("message", message);
658
- });
659
-
660
- //Reset some stuff
661
- if (!ctx.firstListen) ctx.lastSeqId = null;
662
- ctx.syncToken = undefined;
663
- ctx.t_mqttCalled = false;
664
-
665
- //Same request as getThreadList
666
- form = {
667
- "av": ctx.globalOptions.pageID,
668
- "queries": JSON.stringify({
669
- "o0": {
670
- "doc_id": "3336396659757871",
671
- "query_params": {
672
- "limit": 1,
673
- "before": null,
674
- "tags": ["INBOX"],
675
- "includeDeliveryReceipts": false,
676
- "includeSeqID": true
677
- }
678
- }
679
- })
680
- };
681
-
682
- if (!ctx.firstListen || !ctx.lastSeqId) getSeqID();
683
- else listenMqtt(defaultFuncs, api, ctx, globalCallback);
684
- ctx.firstListen = false;
685
- return msgEmitter;
686
- };
687
- };