alicezetion 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -1
  2. package/.cache/replit/nix/env.json +1 -1
  3. package/alice/addExternalModule.js +19 -0
  4. package/alice/{add.js → addUserToGroup.js} +16 -2
  5. package/alice/{admin.js → changeAdminStatus.js} +17 -3
  6. package/alice/{archive.js → changeArchivedStatus.js} +16 -2
  7. package/alice/changeBio.js +77 -0
  8. package/alice/changeBlockedStatus.js +47 -0
  9. package/alice/{gcimage.js → changeGroupImage.js} +16 -2
  10. package/alice/{nickname.js → changeNickname.js} +17 -2
  11. package/alice/changeThreadColor.js +71 -0
  12. package/alice/{emoji.js → changeThreadEmoji.js} +16 -2
  13. package/alice/createNewGroup.js +86 -0
  14. package/alice/{poll.js → createPoll.js} +18 -2
  15. package/alice/{deletemsg.js → deleteMessage.js} +15 -2
  16. package/alice/{deletegc.js → deleteThread.js} +15 -2
  17. package/alice/{forward.js → forwardAttachment.js} +16 -3
  18. package/alice/{id.js → getCurrentUserID.js} +1 -1
  19. package/alice/{friend.js → getFriendsList.js} +17 -3
  20. package/alice/{history.js → getThreadHistory.js} +19 -6
  21. package/alice/{gchistorydeprecated.js → getThreadHistoryDeprecated.js} +18 -1
  22. package/alice/{gcinfo.js → getThreadInfo.js} +49 -13
  23. package/alice/{gcinfodeprecated.js → getThreadInfoDeprecated.js} +17 -2
  24. package/alice/{gclist.js → getThreadList.js} +27 -9
  25. package/alice/{gclistdeprecated.js → getThreadListDeprecated.js} +1 -1
  26. package/alice/{gcimg.js → getThreadPictures.js} +15 -2
  27. package/alice/{userid.js → getUserID.js} +16 -2
  28. package/alice/{userinfo.js → getUserInfo.js} +18 -3
  29. package/alice/handleFriendRequest.js +61 -0
  30. package/alice/{msgrequest.js → handleMessageRequest.js} +16 -2
  31. package/alice/httpGet.js +52 -0
  32. package/alice/httpPost.js +52 -0
  33. package/alice/listenMqtt.js +363 -134
  34. package/alice/logout.js +18 -2
  35. package/alice/{delivered.js → markAsDelivered.js} +19 -2
  36. package/alice/markAsRead.js +80 -0
  37. package/alice/{seen.js → markAsReadAll.js} +16 -2
  38. package/alice/markAsSeen.js +59 -0
  39. package/alice/{mute.js → muteThread.js} +16 -2
  40. package/alice/{kick.js → removeUserFromGroup.js} +16 -2
  41. package/alice/{resolveimgurl.js → resolvePhotoUrl.js} +16 -2
  42. package/alice/{gcsearch.js → searchForThread.js} +16 -2
  43. package/alice/{chat.js → sendMessage.js} +78 -34
  44. package/alice/sendTypingIndicator.js +103 -0
  45. package/alice/{react.js → setMessageReaction.js} +39 -4
  46. package/alice/setPostReaction.js +76 -0
  47. package/alice/{title.js → setTitle.js} +16 -3
  48. package/alice/threadColors.js +57 -0
  49. package/alice/unfriend.js +52 -0
  50. package/alice/{unsend.js → unsendMessage.js} +16 -2
  51. package/index.js +324 -143
  52. package/package.json +27 -18
  53. package/utils.js +137 -61
  54. package/.cache/replit/modules.stamp +0 -0
  55. package/README.md +0 -40
  56. package/alice/block.js +0 -72
  57. package/alice/color.js +0 -53
  58. package/alice/gcolor.js +0 -22
  59. package/alice/listen.js +0 -553
  60. package/alice/read.js +0 -52
  61. package/alice/typeindicator.js +0 -77
  62. /package/alice/{emojiurl.js → getEmojiUrl.js} +0 -0
@@ -4,34 +4,43 @@ var utils = require("../utils");
4
4
  var log = require("npmlog");
5
5
  var mqtt = require('mqtt');
6
6
  var websocket = require('websocket-stream');
7
+ var HttpsProxyAgent = require('https-proxy-agent');
8
+ const EventEmitter = require('events');
7
9
 
8
- var identity = function () {};
9
-
10
- //Don't really know what this does but I think it's for the active state
11
- //TODO: Move to ctx when implemented
12
- var chatOn = true;
13
- var foreground = false;
10
+ var identity = function () { };
11
+ var form = {};
12
+ var getSeqID = function () { };
14
13
 
15
14
  var topics = [
16
- "/t_ms",
17
- "/thread_typing",
18
- "/orca_typing_notifications",
19
- "/orca_presence",
20
15
  "/legacy_web",
21
- "/br_sr",
22
- "/sr_res",
23
16
  "/webrtc",
17
+ "/rtc_multi",
24
18
  "/onevc",
19
+ "/br_sr", //Notification
20
+ //Need to publish /br_sr right after this
21
+ "/sr_res",
22
+ "/t_ms",
23
+ "/thread_typing",
24
+ "/orca_typing_notifications",
25
25
  "/notify_disconnect",
26
- "/inbox",
27
- "/mercury",
28
- "/messaging_events",
29
- "/orca_message_notifications",
30
- "/pp",
31
- "/webrtc_response",
26
+ //Need to publish /messenger_sync_create_queue right after this
27
+ "/orca_presence",
28
+ //Will receive /sr_res right here.
29
+
30
+ //"/inbox",
31
+ //"/mercury",
32
+ //"/messaging_events",
33
+ //"/orca_message_notifications",
34
+ //"/pp",
35
+ //"/webrtc_response",
32
36
  ];
33
37
 
34
- function listenMqtt(defaultFuncs, bot, ctx, globalCallback) {
38
+ function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
39
+ //Don't really know what this does but I think it's for the active state?
40
+ //TODO: Move to ctx when implemented
41
+ var chatOn = ctx.globalOptions.online;
42
+ var foreground = false;
43
+
35
44
  var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
36
45
  var username = {
37
46
  u: ctx.userID,
@@ -45,17 +54,23 @@ function listenMqtt(defaultFuncs, bot, ctx, globalCallback) {
45
54
  mqtt_sid: "",
46
55
  cp: 3,
47
56
  ecp: 10,
48
- st: topics,
57
+ st: [],
49
58
  pm: [],
50
59
  dc: "",
51
60
  no_auto_fg: true,
52
- gas: null
61
+ gas: null,
62
+ pack: []
53
63
  };
54
64
  var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
55
65
 
56
- //Region could be changed for better ping. (Region atn: Southeast Asia, region ash: West US, prob) (Don't really know if we need it).
57
- //// var host = 'wss://edge-chat.facebook.com/chat?region=atn&sid=' + sessionID;
58
- var host = 'wss://edge-chat.facebook.com/chat?sid=' + sessionID;
66
+ var host;
67
+ if (ctx.mqttEndpoint) {
68
+ host = `${ctx.mqttEndpoint}&sid=${sessionID}`;
69
+ } else if (ctx.region) {
70
+ host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}`;
71
+ } else {
72
+ host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}`;
73
+ }
59
74
 
60
75
  var options = {
61
76
  clientId: "mqttwsclient",
@@ -68,25 +83,43 @@ function listenMqtt(defaultFuncs, bot, ctx, globalCallback) {
68
83
  'Cookie': cookies,
69
84
  'Origin': 'https://www.facebook.com',
70
85
  'User-Agent': ctx.globalOptions.userAgent,
71
- 'Referer': 'https://www.facebook.com',
72
- 'Host': 'edge-chat.facebook.com'
86
+ 'Referer': 'https://www.facebook.com/',
87
+ 'Host': new URL(host).hostname //'edge-chat.facebook.com'
73
88
  },
74
89
  origin: 'https://www.facebook.com',
75
90
  protocolVersion: 13
76
- }
91
+ },
92
+ keepalive: 10,
93
+ reschedulePings: false
77
94
  };
78
95
 
96
+ if (typeof ctx.globalOptions.proxy != "undefined") {
97
+ var agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
98
+ options.wsOptions.agent = agent;
99
+ }
100
+
79
101
  ctx.mqttClient = new mqtt.Client(_ => websocket(host, options.wsOptions), options);
80
102
 
81
103
  var mqttClient = ctx.mqttClient;
82
104
 
83
- mqttClient.on('error', function(err) {
84
- log.error(err);
105
+ mqttClient.on('error', function (err) {
106
+ console.error("listenMqtt", err);
85
107
  mqttClient.end();
86
- globalCallback("Connection refused: Server unavailable", null);
108
+ if (ctx.globalOptions.autoReconnect) {
109
+ getSeqID();
110
+ } else {
111
+ globalCallback({
112
+ type: "stop_listen",
113
+ error: "Connection refused: Server unavailable"
114
+ }, null);
115
+ }
87
116
  });
88
117
 
89
- mqttClient.on('connect', function() {
118
+ mqttClient.on('connect', function () {
119
+ topics.forEach(function (topicsub) {
120
+ mqttClient.subscribe(topicsub);
121
+ });
122
+
90
123
  var topic;
91
124
  var queue = {
92
125
  sync_api_version: 10,
@@ -96,11 +129,7 @@ function listenMqtt(defaultFuncs, bot, ctx, globalCallback) {
96
129
  entity_fbid: ctx.userID,
97
130
  };
98
131
 
99
- if(ctx.globalOptions.pageID) {
100
- queue.entity_fbid = ctx.globalOptions.pageID;
101
- }
102
-
103
- if(ctx.syncToken) {
132
+ if (ctx.syncToken) {
104
133
  topic = "/messenger_sync_get_diffs";
105
134
  queue.last_seq_id = ctx.lastSeqId;
106
135
  queue.sync_token = ctx.syncToken;
@@ -109,27 +138,45 @@ function listenMqtt(defaultFuncs, bot, ctx, globalCallback) {
109
138
  queue.initial_titan_sequence_id = ctx.lastSeqId;
110
139
  queue.device_params = null;
111
140
  }
112
-
113
- mqttClient.publish(topic, JSON.stringify(queue), {qos: 1, retain: false});
141
+
142
+ mqttClient.publish(topic, JSON.stringify(queue), { qos: 1, retain: false });
143
+
144
+ var rTimeout = setTimeout(function () {
145
+ mqttClient.end();
146
+ getSeqID();
147
+ }, 5000);
148
+
149
+ ctx.tmsWait = function () {
150
+ clearTimeout(rTimeout);
151
+ ctx.globalOptions.emitReady ? globalCallback({
152
+ type: "ready",
153
+ error: null
154
+ }) : "";
155
+ delete ctx.tmsWait;
156
+ };
114
157
  });
115
158
 
116
- mqttClient.on('message', function(topic, message, packet) {
117
- var jsonMessage = JSON.parse(message);
118
- if(topic === "/t_ms") {
119
- if(jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
159
+ mqttClient.on('message', function (topic, message, _packet) {
160
+ try {
161
+ var jsonMessage = JSON.parse(message);
162
+ } catch (ex) {
163
+ return;
164
+ //console.error("listenMqtt", "JSON conversion failed");
165
+ }
166
+ if (topic === "/t_ms") {
167
+ if (ctx.tmsWait && typeof ctx.tmsWait == "function") {
168
+ ctx.tmsWait();
169
+ }
170
+
171
+ if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
120
172
  ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
121
173
  ctx.syncToken = jsonMessage.syncToken;
122
174
  }
123
175
 
124
- if(jsonMessage.lastIssuedSeqId) {
176
+ if (jsonMessage.lastIssuedSeqId) {
125
177
  ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
126
178
  }
127
179
 
128
- if(jsonMessage.queueEntityId && ctx.globalOptions.pageID &&
129
- ctx.globalOptions.pageID != jsonMessage.queueEntityId) {
130
- return;
131
- }
132
-
133
180
  //If it contains more than 1 delta
134
181
  for (var i in jsonMessage.deltas) {
135
182
  var delta = jsonMessage.deltas[i];
@@ -163,16 +210,22 @@ function listenMqtt(defaultFuncs, bot, ctx, globalCallback) {
163
210
 
164
211
  });
165
212
 
166
- mqttClient.on('close', function() {
213
+ mqttClient.on('close', function () {
214
+ //(function () { globalCallback("Connection closed."); })();
167
215
  // client.end();
168
216
  });
169
217
  }
170
218
 
171
219
  function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
172
- if(v.delta.class == "NewMessage") {
220
+ if (v.delta.class == "NewMessage") {
221
+ //Not tested for pages
222
+ if (ctx.globalOptions.pageID &&
223
+ ctx.globalOptions.pageID != v.queue
224
+ )
225
+ return;
226
+
173
227
  (function resolveAttachmentUrl(i) {
174
- // sometimes, with sticker message in group, delta does not contain 'attachments' property.
175
- if (v.delta.attachments && (i == v.delta.attachments.length)) {
228
+ if (i == v.delta.attachments.length) {
176
229
  var fmtMsg;
177
230
  try {
178
231
  fmtMsg = utils.formatDeltaMessage(v);
@@ -195,7 +248,7 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
195
248
  (function () { globalCallback(null, fmtMsg); })();
196
249
  } else {
197
250
  if (
198
- v.delta.attachments && (v.delta.attachments[i].mercury.attach_type == "photo")
251
+ v.delta.attachments[i].mercury.attach_type == "photo"
199
252
  ) {
200
253
  api.resolvePhotoUrl(
201
254
  v.delta.attachments[i].fbid,
@@ -222,28 +275,32 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
222
275
  for (var i in clientPayload.deltas) {
223
276
  var delta = clientPayload.deltas[i];
224
277
  if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
225
- (function () { globalCallback(null, {
226
- type: "message_reaction",
227
- threadID: (delta.deltaMessageReaction.threadKey
228
- .threadFbId ?
229
- delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey
230
- .otherUserFbId).toString(),
231
- messageID: delta.deltaMessageReaction.messageId,
232
- reaction: delta.deltaMessageReaction.reaction,
233
- senderID: delta.deltaMessageReaction.senderId.toString(),
234
- userID: delta.deltaMessageReaction.userId.toString()
235
- }); })();
278
+ (function () {
279
+ globalCallback(null, {
280
+ type: "message_reaction",
281
+ threadID: (delta.deltaMessageReaction.threadKey
282
+ .threadFbId ?
283
+ delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey
284
+ .otherUserFbId).toString(),
285
+ messageID: delta.deltaMessageReaction.messageId,
286
+ reaction: delta.deltaMessageReaction.reaction,
287
+ senderID: delta.deltaMessageReaction.senderId.toString(),
288
+ userID: delta.deltaMessageReaction.userId.toString()
289
+ });
290
+ })();
236
291
  } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
237
- (function () { globalCallback(null, {
238
- type: "message_unsend",
239
- threadID: (delta.deltaRecallMessageData.threadKey.threadFbId ?
240
- delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey
241
- .otherUserFbId).toString(),
242
- messageID: delta.deltaRecallMessageData.messageID,
243
- senderID: delta.deltaRecallMessageData.senderID.toString(),
244
- deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
245
- timestamp: delta.deltaRecallMessageData.timestamp
246
- }); })();
292
+ (function () {
293
+ globalCallback(null, {
294
+ type: "message_unsend",
295
+ threadID: (delta.deltaRecallMessageData.threadKey.threadFbId ?
296
+ delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey
297
+ .otherUserFbId).toString(),
298
+ messageID: delta.deltaRecallMessageData.messageID,
299
+ senderID: delta.deltaRecallMessageData.senderID.toString(),
300
+ deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
301
+ timestamp: delta.deltaRecallMessageData.timestamp
302
+ });
303
+ })();
247
304
  } else if (delta.deltaMessageReply) {
248
305
  //Mention block - #1
249
306
  var mdata =
@@ -336,8 +393,79 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
336
393
  body: delta.deltaMessageReply.repliedToMessage.body || "",
337
394
  isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
338
395
  mentions: rmentions,
339
- timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp,
396
+ timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp
340
397
  };
398
+ } else if (delta.deltaMessageReply.replyToMessageId) {
399
+ return defaultFuncs
400
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
401
+ "av": ctx.globalOptions.pageID,
402
+ "queries": JSON.stringify({
403
+ "o0": {
404
+ //Using the same doc_id as forcedFetch
405
+ "doc_id": "2848441488556444",
406
+ "query_params": {
407
+ "thread_and_message_id": {
408
+ "thread_id": callbackToReturn.threadID,
409
+ "message_id": delta.deltaMessageReply.replyToMessageId.id,
410
+ }
411
+ }
412
+ }
413
+ })
414
+ })
415
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
416
+ .then((resData) => {
417
+ if (resData[resData.length - 1].error_results > 0) {
418
+ throw resData[0].o0.errors;
419
+ }
420
+
421
+ if (resData[resData.length - 1].successful_results === 0) {
422
+ throw { error: "forcedFetch: there was no successful_results", res: resData };
423
+ }
424
+
425
+ var fetchData = resData[0].o0.data.message;
426
+
427
+ var mobj = {};
428
+ for (var n in fetchData.message.ranges) {
429
+ mobj[fetchData.message.ranges[n].entity.id] = (fetchData.message.text || "").substr(fetchData.message.ranges[n].offset, fetchData.message.ranges[n].length);
430
+ }
431
+
432
+ callbackToReturn.messageReply = {
433
+ threadID: callbackToReturn.threadID,
434
+ messageID: fetchData.message_id,
435
+ senderID: fetchData.message_sender.id.toString(),
436
+ attachments: fetchData.message.blob_attachment.map(att => {
437
+ var x;
438
+ try {
439
+ x = utils._formatAttachment({
440
+ blob_attachment: att
441
+ });
442
+ } catch (ex) {
443
+ x = att;
444
+ x.error = ex;
445
+ x.type = "unknown";
446
+ }
447
+ return x;
448
+ }),
449
+ body: fetchData.message.text || "",
450
+ isGroup: callbackToReturn.isGroup,
451
+ mentions: mobj,
452
+ timestamp: parseInt(fetchData.timestamp_precise)
453
+ };
454
+ })
455
+ .catch((err) => {
456
+ console.error("forcedFetch", err);
457
+ })
458
+ .finally(function () {
459
+ if (ctx.globalOptions.autoMarkDelivery) {
460
+ markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
461
+ }
462
+ !ctx.globalOptions.selfListen &&
463
+ callbackToReturn.senderID === ctx.userID ?
464
+ undefined :
465
+ (function () { globalCallback(null, callbackToReturn); })();
466
+ });
467
+ } else {
468
+ callbackToReturn.delta = delta;
341
469
  }
342
470
 
343
471
  if (ctx.globalOptions.autoMarkDelivery) {
@@ -406,12 +534,12 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
406
534
  "av": ctx.globalOptions.pageID,
407
535
  "queries": JSON.stringify({
408
536
  "o0": {
409
- //This doc_id is valid as of ? (prob January 18, 2020)
410
- "doc_id": "1768656253222505",
537
+ //This doc_id is valid as of March 25, 2020
538
+ "doc_id": "2848441488556444",
411
539
  "query_params": {
412
540
  "thread_and_message_id": {
413
541
  "thread_id": tid.toString(),
414
- "message_id": mid.toString(),
542
+ "message_id": mid,
415
543
  }
416
544
  }
417
545
  }
@@ -431,28 +559,95 @@ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
431
559
  }
432
560
 
433
561
  var fetchData = resData[0].o0.data.message;
434
- if (fetchData && fetchData.__typename === "ThreadImageMessage") {
435
- (!ctx.globalOptions.selfListen &&
436
- fetchData.message_sender.id.toString() === ctx.userID) ||
437
- !ctx.loggedIn ?
438
- undefined :
439
- (function () { globalCallback(null, {
440
- type: "change_thread_image",
441
- threadID: utils.formatID(tid.toString()),
442
- snippet: fetchData.snippet,
443
- timestamp: fetchData.timestamp_precise,
444
- author: fetchData.message_sender.id,
445
- image: {
446
- attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
447
- width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
448
- height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
449
- url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
450
- }
451
- }); })();
562
+
563
+ if (utils.getType(fetchData) == "Object") {
564
+ log.info("forcedFetch", fetchData);
565
+ switch (fetchData.__typename) {
566
+ case "ThreadImageMessage":
567
+ (!ctx.globalOptions.selfListen &&
568
+ fetchData.message_sender.id.toString() === ctx.userID) ||
569
+ !ctx.loggedIn ?
570
+ undefined :
571
+ (function () {
572
+ globalCallback(null, {
573
+ type: "change_thread_image",
574
+ threadID: utils.formatID(tid.toString()),
575
+ snippet: fetchData.snippet,
576
+ timestamp: fetchData.timestamp_precise,
577
+ author: fetchData.message_sender.id,
578
+ image: {
579
+ attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
580
+ width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
581
+ height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
582
+ url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
583
+ }
584
+ });
585
+ })();
586
+ break;
587
+ case "UserMessage":
588
+ log.info("ff-Return", {
589
+ type: "message",
590
+ senderID: utils.formatID(fetchData.message_sender.id),
591
+ body: fetchData.message.text || "",
592
+ threadID: utils.formatID(tid.toString()),
593
+ messageID: fetchData.message_id,
594
+ attachments: [{
595
+ type: "share",
596
+ ID: fetchData.extensible_attachment.legacy_attachment_id,
597
+ url: fetchData.extensible_attachment.story_attachment.url,
598
+
599
+ title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
600
+ description: fetchData.extensible_attachment.story_attachment.description.text,
601
+ source: fetchData.extensible_attachment.story_attachment.source,
602
+
603
+ image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
604
+ width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
605
+ height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
606
+ playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
607
+ duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
608
+
609
+ subattachments: fetchData.extensible_attachment.subattachments,
610
+ properties: fetchData.extensible_attachment.story_attachment.properties,
611
+ }],
612
+ mentions: {},
613
+ timestamp: parseInt(fetchData.timestamp_precise),
614
+ isGroup: (fetchData.message_sender.id != tid.toString())
615
+ });
616
+ globalCallback(null, {
617
+ type: "message",
618
+ senderID: utils.formatID(fetchData.message_sender.id),
619
+ body: fetchData.message.text || "",
620
+ threadID: utils.formatID(tid.toString()),
621
+ messageID: fetchData.message_id,
622
+ attachments: [{
623
+ type: "share",
624
+ ID: fetchData.extensible_attachment.legacy_attachment_id,
625
+ url: fetchData.extensible_attachment.story_attachment.url,
626
+
627
+ title: fetchData.extensible_attachment.story_attachment.title_with_entities.text,
628
+ description: fetchData.extensible_attachment.story_attachment.description.text,
629
+ source: fetchData.extensible_attachment.story_attachment.source,
630
+
631
+ image: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).uri,
632
+ width: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).width,
633
+ height: ((fetchData.extensible_attachment.story_attachment.media || {}).image || {}).height,
634
+ playable: (fetchData.extensible_attachment.story_attachment.media || {}).is_playable || false,
635
+ duration: (fetchData.extensible_attachment.story_attachment.media || {}).playable_duration_in_ms || 0,
636
+
637
+ subattachments: fetchData.extensible_attachment.subattachments,
638
+ properties: fetchData.extensible_attachment.story_attachment.properties,
639
+ }],
640
+ mentions: {},
641
+ timestamp: parseInt(fetchData.timestamp_precise),
642
+ isGroup: (fetchData.message_sender.id != tid.toString())
643
+ });
644
+ }
645
+ } else {
646
+ console.error("forcedFetch", fetchData);
452
647
  }
453
648
  })
454
649
  .catch((err) => {
455
- log.error("forcedFetch", err);
650
+ console.error("forcedFetch", err);
456
651
  });
457
652
  }
458
653
  break;
@@ -482,12 +677,12 @@ function markDelivery(ctx, api, threadID, messageID) {
482
677
  if (threadID && messageID) {
483
678
  api.markAsDelivered(threadID, messageID, (err) => {
484
679
  if (err) {
485
- log.error(err);
680
+ console.error("markAsDelivered", err);
486
681
  } else {
487
682
  if (ctx.globalOptions.autoMarkRead) {
488
683
  api.markAsRead(threadID, (err) => {
489
684
  if (err) {
490
- log.error(err);
685
+ console.error("markAsDelivered", err);
491
686
  }
492
687
  });
493
688
  }
@@ -498,35 +693,20 @@ function markDelivery(ctx, api, threadID, messageID) {
498
693
 
499
694
  module.exports = function (defaultFuncs, api, ctx) {
500
695
  var globalCallback = identity;
501
- return function (callback) {
502
- globalCallback = callback;
503
-
504
- //Reset some stuff
505
- ctx.lastSeqId = 0;
506
- ctx.syncToken = undefined;
507
-
508
- //Same request as getThreadList
509
- const form = {
510
- "av": ctx.globalOptions.pageID,
511
- "queries": JSON.stringify({
512
- "o0": {
513
- "doc_id": "1349387578499440",
514
- "query_params": {
515
- "limit": 1,
516
- "before": null,
517
- "tags": ["INBOX"],
518
- "includeDeliveryReceipts": false,
519
- "includeSeqID": true
520
- }
521
- }
522
- })
523
- };
524
-
696
+ getSeqID = function getSeqID() {
697
+ ctx.t_mqttCalled = false;
525
698
  defaultFuncs
526
699
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
527
700
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
528
701
  .then((resData) => {
529
- if (resData && resData.length > 0 && resData[resData.length - 1].error_results > 0) {
702
+ if (utils.getType(resData) != "Array") {
703
+ throw {
704
+ error: "Not logged in",
705
+ res: resData
706
+ };
707
+ }
708
+
709
+ if (resData && resData[resData.length - 1].error_results > 0) {
530
710
  throw resData[0].o0.errors;
531
711
  }
532
712
 
@@ -537,24 +717,73 @@ module.exports = function (defaultFuncs, api, ctx) {
537
717
  if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
538
718
  ctx.lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
539
719
  listenMqtt(defaultFuncs, api, ctx, globalCallback);
720
+ } else {
721
+ throw { error: "getSeqId: no sync_sequence_id found.", res: resData };
540
722
  }
541
-
542
723
  })
543
724
  .catch((err) => {
544
- log.error("getSeqId", err);
545
- return callback(err);
725
+ console.error("getSeqId", err);
726
+ if (utils.getType(err) == "Object" && err.error === "Not logged in") {
727
+ ctx.loggedIn = false;
728
+ }
729
+ return globalCallback(err);
546
730
  });
731
+ };
547
732
 
548
- var stopListening = function () {
549
- globalCallback = identity;
733
+ return function (callback) {
734
+ class MessageEmitter extends EventEmitter {
735
+ stopListening(callback) {
736
+ callback = callback || (() => { });
737
+ globalCallback = identity;
738
+ if (ctx.mqttClient) {
739
+ ctx.mqttClient.unsubscribe("/webrtc");
740
+ ctx.mqttClient.unsubscribe("/rtc_multi");
741
+ ctx.mqttClient.unsubscribe("/onevc");
742
+ ctx.mqttClient.publish("/browser_close", "{}");
743
+ ctx.mqttClient.end(false, function (...data) {
744
+ callback(data);
745
+ ctx.mqttClient = undefined;
746
+ });
747
+ }
748
+ }
749
+ }
550
750
 
551
- if(ctx.mqttClient)
552
- {
553
- ctx.mqttClient.end();
554
- ctx.mqttClient = undefined;
751
+ var msgEmitter = new MessageEmitter();
752
+ globalCallback = (callback || function (error, message) {
753
+ if (error) {
754
+ return msgEmitter.emit("error", error);
555
755
  }
756
+ msgEmitter.emit("message", message);
757
+ });
758
+
759
+ //Reset some stuff
760
+ if (!ctx.firstListen) ctx.lastSeqId = null;
761
+ ctx.syncToken = undefined;
762
+ ctx.t_mqttCalled = false;
763
+
764
+ //Same request as getThreadList
765
+ form = {
766
+ "av": ctx.globalOptions.pageID,
767
+ "queries": JSON.stringify({
768
+ "o0": {
769
+ "doc_id": "3336396659757871",
770
+ "query_params": {
771
+ "limit": 1,
772
+ "before": null,
773
+ "tags": ["INBOX"],
774
+ "includeDeliveryReceipts": false,
775
+ "includeSeqID": true
776
+ }
777
+ }
778
+ })
556
779
  };
557
780
 
558
- return stopListening;
781
+ if (!ctx.firstListen || !ctx.lastSeqId) {
782
+ getSeqID();
783
+ } else {
784
+ listenMqtt(defaultFuncs, api, ctx, globalCallback);
785
+ }
786
+ ctx.firstListen = false;
787
+ return msgEmitter;
559
788
  };
560
789
  };