@cexy/hoonfca 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/CHANGELOG.md +181 -0
  2. package/DOCS.md +2636 -0
  3. package/LICENSE-MIT +21 -21
  4. package/README.md +632 -0
  5. package/func/checkUpdate.js +222 -0
  6. package/func/logger.js +48 -0
  7. package/index.d.ts +731 -605
  8. package/index.js +6 -777
  9. package/module/config.js +34 -0
  10. package/module/login.js +136 -0
  11. package/module/loginHelper.js +1034 -0
  12. package/module/options.js +45 -0
  13. package/package.json +53 -22
  14. package/src/api/action/addExternalModule.js +25 -0
  15. package/src/api/action/changeAvatar.js +137 -0
  16. package/src/{changeBio.js → api/action/changeBio.js} +75 -76
  17. package/src/api/action/enableAutoSaveAppState.js +73 -0
  18. package/src/{getCurrentUserID.js → api/action/getCurrentUserID.js} +7 -7
  19. package/src/{handleFriendRequest.js → api/action/handleFriendRequest.js} +57 -57
  20. package/src/api/action/logout.js +76 -0
  21. package/src/api/action/refreshFb_dtsg.js +48 -0
  22. package/src/api/action/setPostReaction.js +106 -0
  23. package/src/api/action/unfriend.js +54 -0
  24. package/src/api/http/httpGet.js +46 -0
  25. package/src/api/http/httpPost.js +52 -0
  26. package/src/api/http/postFormData.js +47 -0
  27. package/src/api/messaging/addUserToGroup.js +68 -0
  28. package/src/api/messaging/changeAdminStatus.js +122 -0
  29. package/src/api/messaging/changeArchivedStatus.js +55 -0
  30. package/src/api/messaging/changeBlockedStatus.js +48 -0
  31. package/src/api/messaging/changeGroupImage.js +90 -0
  32. package/src/api/messaging/changeNickname.js +70 -0
  33. package/src/api/messaging/changeThreadColor.js +79 -0
  34. package/src/api/messaging/changeThreadEmoji.js +106 -0
  35. package/src/{createNewGroup.js → api/messaging/createNewGroup.js} +88 -88
  36. package/src/api/messaging/createPoll.js +43 -0
  37. package/src/api/messaging/createThemeAI.js +98 -0
  38. package/src/{deleteMessage.js → api/messaging/deleteMessage.js} +56 -56
  39. package/src/{deleteThread.js → api/messaging/deleteThread.js} +56 -56
  40. package/src/api/messaging/editMessage.js +68 -0
  41. package/src/api/messaging/forwardAttachment.js +51 -0
  42. package/src/{getEmojiUrl.js → api/messaging/getEmojiUrl.js} +8 -8
  43. package/src/{getFriendsList.js → api/messaging/getFriendsList.js} +82 -84
  44. package/src/api/messaging/getMessage.js +829 -0
  45. package/src/api/messaging/getThemePictures.js +62 -0
  46. package/src/api/messaging/handleMessageRequest.js +65 -0
  47. package/src/{markAsDelivered.js → api/messaging/markAsDelivered.js} +57 -58
  48. package/src/{markAsRead.js → api/messaging/markAsRead.js} +88 -88
  49. package/src/{markAsReadAll.js → api/messaging/markAsReadAll.js} +49 -50
  50. package/src/api/messaging/markAsSeen.js +61 -0
  51. package/src/{muteThread.js → api/messaging/muteThread.js} +50 -52
  52. package/src/api/messaging/removeUserFromGroup.js +106 -0
  53. package/src/{resolvePhotoUrl.js → api/messaging/resolvePhotoUrl.js} +43 -45
  54. package/src/api/messaging/scheduler.js +264 -0
  55. package/src/{searchForThread.js → api/messaging/searchForThread.js} +52 -53
  56. package/src/api/messaging/sendMessage.js +272 -0
  57. package/src/api/messaging/sendTypingIndicator.js +67 -0
  58. package/src/api/messaging/setMessageReaction.js +76 -0
  59. package/src/api/messaging/setTitle.js +119 -0
  60. package/src/{shareContact.js → api/messaging/shareContact.js} +49 -53
  61. package/src/api/messaging/threadColors.js +128 -0
  62. package/src/api/messaging/unsendMessage.js +81 -0
  63. package/src/api/messaging/uploadAttachment.js +94 -0
  64. package/src/api/socket/core/connectMqtt.js +255 -0
  65. package/src/api/socket/core/emitAuth.js +106 -0
  66. package/src/api/socket/core/getSeqID.js +40 -0
  67. package/src/api/socket/core/getTaskResponseData.js +22 -0
  68. package/src/api/socket/core/markDelivery.js +12 -0
  69. package/src/api/socket/core/parseDelta.js +391 -0
  70. package/src/api/socket/detail/buildStream.js +208 -0
  71. package/src/api/socket/detail/constants.js +24 -0
  72. package/src/api/socket/listenMqtt.js +364 -0
  73. package/src/api/socket/middleware/index.js +216 -0
  74. package/src/{getThreadHistory.js → api/threads/getThreadHistory.js} +664 -647
  75. package/src/api/threads/getThreadInfo.js +438 -0
  76. package/src/{getThreadList.js → api/threads/getThreadList.js} +293 -292
  77. package/src/{getThreadPictures.js → api/threads/getThreadPictures.js} +78 -79
  78. package/src/{getUserID.js → api/users/getUserID.js} +65 -66
  79. package/src/api/users/getUserInfo.js +327 -0
  80. package/src/api/users/getUserInfoV2.js +134 -0
  81. package/src/core/sendReqMqtt.js +96 -0
  82. package/src/database/models/index.js +87 -0
  83. package/src/database/models/thread.js +45 -0
  84. package/src/database/models/user.js +46 -0
  85. package/src/database/threadData.js +98 -0
  86. package/src/database/userData.js +89 -0
  87. package/src/utils/client.js +320 -0
  88. package/src/utils/constants.js +23 -0
  89. package/{utils.js → src/utils/format.js} +1115 -1447
  90. package/src/utils/headers.js +115 -0
  91. package/src/utils/request.js +305 -0
  92. package/.travis.yml +0 -6
  93. package/src/addExternalModule.js +0 -23
  94. package/src/addUserToGroup.js +0 -113
  95. package/src/changeAdminStatus.js +0 -95
  96. package/src/changeApprovalMode.js +0 -79
  97. package/src/changeArchivedStatus.js +0 -55
  98. package/src/changeBlockedStatus.js +0 -47
  99. package/src/changeBlockedStatusMqtt.js +0 -86
  100. package/src/changeGroupImage.js +0 -133
  101. package/src/changeNickname.js +0 -59
  102. package/src/changeThreadColor.js +0 -71
  103. package/src/changeThreadEmoji.js +0 -55
  104. package/src/createPoll.js +0 -130
  105. package/src/editMessage.js +0 -63
  106. package/src/forwardAttachment.js +0 -60
  107. package/src/forwardMessage.js +0 -63
  108. package/src/getGroupsList.js +0 -83
  109. package/src/getMarketplace.js +0 -84
  110. package/src/getNotifications.js +0 -86
  111. package/src/getPagesList.js +0 -83
  112. package/src/getStories.js +0 -88
  113. package/src/getThreadInfo.js +0 -222
  114. package/src/getUserInfo.js +0 -128
  115. package/src/handleMessageRequest.js +0 -65
  116. package/src/httpGet.js +0 -58
  117. package/src/httpPost.js +0 -58
  118. package/src/listenMqtt.js +0 -1018
  119. package/src/logout.js +0 -75
  120. package/src/markAsSeen.js +0 -61
  121. package/src/pinMessage.js +0 -61
  122. package/src/removeUserFromGroup.js +0 -79
  123. package/src/searchUsers.js +0 -89
  124. package/src/sendComment.js +0 -161
  125. package/src/sendMessage.js +0 -457
  126. package/src/sendTypingIndicator.js +0 -179
  127. package/src/setBio.js +0 -86
  128. package/src/setMessageReaction.js +0 -186
  129. package/src/setPostReaction.js +0 -71
  130. package/src/setTheme.js +0 -313
  131. package/src/setTitle.js +0 -90
  132. package/src/shareLink.js +0 -62
  133. package/src/threadColors.js +0 -57
  134. package/src/unfriend.js +0 -53
  135. package/src/unsendMessage.js +0 -104
package/src/listenMqtt.js DELETED
@@ -1,1018 +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
- var identity = function () {};
11
- var form = {};
12
- var getSeqID = function () {};
13
-
14
- var topics = [
15
- "/legacy_web",
16
- "/webrtc",
17
- "/rtc_multi",
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
- "/notify_disconnect",
26
- //Need to publish /messenger_sync_create_queue right after this
27
- "/orca_presence",
28
- //Will receive /sr_res right here.
29
-
30
- "/ls_resp",
31
- // "/ls_req",
32
-
33
- "/inbox",
34
- "/mercury",
35
- "/messaging_events",
36
- "/orca_message_notifications",
37
- "/pp",
38
- "/webrtc_response",
39
- ];
40
-
41
- function listenMqtt(defaultFuncs, api, ctx, globalCallback) {
42
- //Don't really know what this does but I think it's for the active state?
43
- //TODO: Move to ctx when implemented
44
- var chatOn = ctx.globalOptions.online;
45
- var foreground = false;
46
-
47
- ctx["tasks"].clear(); // Clear tasks
48
-
49
- var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
50
- var username = {
51
- u: ctx.userID,
52
- s: sessionID,
53
- chat_on: chatOn,
54
- fg: foreground,
55
- d: utils.getGUID(),
56
- ct: "websocket",
57
- //App id from facebook
58
- aid: "219994525426954",
59
- mqtt_sid: "",
60
- cp: 3,
61
- ecp: 10,
62
- st: [],
63
- pm: [],
64
- dc: "",
65
- no_auto_fg: true,
66
- gas: null,
67
- pack: [],
68
- };
69
- var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
70
-
71
- var host;
72
- if (ctx.mqttEndpoint) {
73
- host = `${ctx.mqttEndpoint}&sid=${sessionID}`;
74
- } else if (ctx.region) {
75
- host = `wss://edge-chat.facebook.com/chat?region=${ctx.region.toLocaleLowerCase()}&sid=${sessionID}`;
76
- } else {
77
- host = `wss://edge-chat.facebook.com/chat?sid=${sessionID}`;
78
- }
79
-
80
- var options = {
81
- clientId: "mqttwsclient",
82
- protocolId: "MQIsdp",
83
- protocolVersion: 3,
84
- username: JSON.stringify(username),
85
- clean: true,
86
- wsOptions: {
87
- headers: {
88
- Cookie: cookies,
89
- Origin: "https://www.facebook.com",
90
- "User-Agent": ctx.globalOptions.userAgent,
91
- Referer: "https://www.facebook.com/",
92
- Host: new URL(host).hostname, //'edge-chat.facebook.com'
93
- },
94
- origin: "https://www.facebook.com",
95
- protocolVersion: 13,
96
- },
97
- keepalive: 10,
98
- reschedulePings: false,
99
- };
100
-
101
- if (typeof ctx.globalOptions.proxy != "undefined") {
102
- var agent = new HttpsProxyAgent(ctx.globalOptions.proxy);
103
- options.wsOptions.agent = agent;
104
- }
105
-
106
- ctx.mqttClient = new mqtt.Client(
107
- (_) => websocket(host, options.wsOptions),
108
- options,
109
- );
110
-
111
- var mqttClient = ctx.mqttClient;
112
-
113
- mqttClient.on("error", function (err) {
114
- log.error("listenMqtt", err);
115
- mqttClient.end();
116
- if (ctx.globalOptions.autoReconnect) {
117
- getSeqID();
118
- } else {
119
- globalCallback(
120
- {
121
- type: "stop_listen",
122
- error: "Connection refused: Server unavailable",
123
- },
124
- null,
125
- );
126
- }
127
- });
128
-
129
- mqttClient.on("connect", function () {
130
- topics.forEach(function (topicsub) {
131
- mqttClient.subscribe(topicsub);
132
- });
133
-
134
- var topic;
135
- var queue = {
136
- sync_api_version: 10,
137
- max_deltas_able_to_process: 1000,
138
- delta_batch_size: 500,
139
- encoding: "JSON",
140
- entity_fbid: ctx.userID,
141
- };
142
-
143
- if (ctx.syncToken) {
144
- topic = "/messenger_sync_get_diffs";
145
- queue.last_seq_id = ctx.lastSeqId;
146
- queue.sync_token = ctx.syncToken;
147
- } else {
148
- topic = "/messenger_sync_create_queue";
149
- queue.initial_titan_sequence_id = ctx.lastSeqId;
150
- queue.device_params = null;
151
- }
152
-
153
- mqttClient.publish(topic, JSON.stringify(queue), {
154
- qos: 1,
155
- retain: false,
156
- });
157
-
158
- var rTimeout = setTimeout(function () {
159
- mqttClient.end();
160
- getSeqID();
161
- }, 5000);
162
-
163
- ctx.tmsWait = function () {
164
- clearTimeout(rTimeout);
165
- ctx.globalOptions.emitReady
166
- ? globalCallback({
167
- type: "ready",
168
- error: null,
169
- })
170
- : "";
171
- delete ctx.tmsWait;
172
- };
173
- });
174
-
175
- mqttClient.on("message", function (topic, message, _packet) {
176
- try {
177
- var jsonMessage = JSON.parse(message);
178
- } catch (ex) {
179
- return log.error("listenMqtt", ex);
180
- }
181
- if (topic === "/t_ms") {
182
- if (ctx.tmsWait && typeof ctx.tmsWait == "function") {
183
- ctx.tmsWait();
184
- }
185
-
186
- if (jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
187
- ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
188
- ctx.syncToken = jsonMessage.syncToken;
189
- }
190
-
191
- if (jsonMessage.lastIssuedSeqId) {
192
- ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
193
- }
194
-
195
- //If it contains more than 1 delta
196
- for (var i in jsonMessage.deltas) {
197
- var delta = jsonMessage.deltas[i];
198
- parseDelta(defaultFuncs, api, ctx, globalCallback, {
199
- delta: delta,
200
- });
201
- }
202
- } else if (
203
- topic === "/thread_typing" ||
204
- topic === "/orca_typing_notifications"
205
- ) {
206
- var typ = {
207
- type: "typ",
208
- isTyping: !!jsonMessage.state,
209
- from: jsonMessage.sender_fbid.toString(),
210
- threadID: utils.formatID(
211
- (jsonMessage.thread || jsonMessage.sender_fbid).toString(),
212
- ),
213
- };
214
- (function () {
215
- globalCallback(null, typ);
216
- })();
217
- } else if (topic === "/orca_presence") {
218
- if (!ctx.globalOptions.updatePresence) {
219
- for (var i in jsonMessage.list) {
220
- var data = jsonMessage.list[i];
221
- var userID = data["u"];
222
-
223
- var presence = {
224
- type: "presence",
225
- userID: userID.toString(),
226
- //Convert to ms
227
- timestamp: data["l"] * 1000,
228
- statuses: data["p"],
229
- };
230
- (function () {
231
- globalCallback(null, presence);
232
- })();
233
- }
234
- }
235
- } else if (topic == "/ls_resp") {
236
- const parsedPayload = JSON.parse(jsonMessage.payload);
237
- const reqID = jsonMessage.request_id;
238
- if (ctx["tasks"].has(reqID)) {
239
- const taskData = ctx["tasks"].get(reqID);
240
- const { type: taskType, callback: taskCallback } = taskData;
241
- const taskRespData = getTaskResponseData(taskType, parsedPayload);
242
-
243
- if (taskRespData == null) {
244
- taskCallback("error", null);
245
- } else {
246
- taskCallback(null, {
247
- type: taskType,
248
- reqID: reqID,
249
- ...taskRespData,
250
- });
251
- }
252
- }
253
- }
254
- });
255
-
256
- mqttClient.on("close", function () {
257
- //(function () { globalCallback("Connection closed."); })();
258
- // client.end();
259
- });
260
- }
261
-
262
- function getTaskResponseData(taskType, payload) {
263
- try {
264
- switch (taskType) {
265
- case "set_message_reaction": {
266
- return {
267
- mid: payload.step[1][2][2][1][4],
268
- };
269
- }
270
- case "edit_message": {
271
- return {
272
- mid: payload.step[1][2][2][1][2],
273
- };
274
- }
275
- }
276
- } catch (error) {
277
- return null;
278
- }
279
- }
280
-
281
- function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
282
- if (v.delta.class == "NewMessage") {
283
- //Not tested for pages
284
- if (ctx.globalOptions.pageID && ctx.globalOptions.pageID != v.queue) return;
285
-
286
- (function resolveAttachmentUrl(i) {
287
- if (v.delta.attachments && i == v.delta.attachments.length) {
288
- var fmtMsg;
289
- try {
290
- fmtMsg = utils.formatDeltaMessage(v);
291
- } catch (err) {
292
- return globalCallback({
293
- error:
294
- "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
295
- detail: err,
296
- res: v,
297
- type: "parse_error",
298
- });
299
- }
300
- if (fmtMsg) {
301
- if (ctx.globalOptions.autoMarkDelivery) {
302
- markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
303
- }
304
- }
305
- return !ctx.globalOptions.selfListen && fmtMsg.senderID === ctx.userID
306
- ? undefined
307
- : (function () {
308
- globalCallback(null, fmtMsg);
309
- })();
310
- } else {
311
- if (v.delta.attachments[i].mercury.attach_type == "photo") {
312
- api.resolvePhotoUrl(v.delta.attachments[i].fbid, (err, url) => {
313
- if (!err) v.delta.attachments[i].mercury.metadata.url = url;
314
- return resolveAttachmentUrl(i + 1);
315
- });
316
- } else {
317
- return resolveAttachmentUrl(i + 1);
318
- }
319
- }
320
- })(0);
321
- }
322
-
323
- if (v.delta.class == "ClientPayload") {
324
- var clientPayload = utils.decodeClientPayload(v.delta.payload);
325
- if (clientPayload && clientPayload.deltas) {
326
- for (var i in clientPayload.deltas) {
327
- var delta = clientPayload.deltas[i];
328
- if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
329
- (function () {
330
- globalCallback(null, {
331
- type: "message_reaction",
332
- threadID: (delta.deltaMessageReaction.threadKey.threadFbId
333
- ? delta.deltaMessageReaction.threadKey.threadFbId
334
- : delta.deltaMessageReaction.threadKey.otherUserFbId
335
- ).toString(),
336
- messageID: delta.deltaMessageReaction.messageId,
337
- reaction: delta.deltaMessageReaction.reaction,
338
- senderID: delta.deltaMessageReaction.senderId.toString(),
339
- userID: delta.deltaMessageReaction.userId.toString(),
340
- reactionTimestamp: delta.deltaMessageReaction.reactionTimestamp,
341
- });
342
- })();
343
- } else if (
344
- delta.deltaRecallMessageData &&
345
- !!ctx.globalOptions.listenEvents
346
- ) {
347
- (function () {
348
- globalCallback(null, {
349
- type: "message_unsend",
350
- threadID: (delta.deltaRecallMessageData.threadKey.threadFbId
351
- ? delta.deltaRecallMessageData.threadKey.threadFbId
352
- : delta.deltaRecallMessageData.threadKey.otherUserFbId
353
- ).toString(),
354
- messageID: delta.deltaRecallMessageData.messageID,
355
- senderID: delta.deltaRecallMessageData.senderID.toString(),
356
- deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
357
- timestamp: delta.deltaRecallMessageData.messageTimestamp,
358
- });
359
- })();
360
- } else if (delta.deltaMessageReply) {
361
- //Mention block - #1
362
- var mdata =
363
- delta.deltaMessageReply.message === undefined
364
- ? []
365
- : delta.deltaMessageReply.message.data === undefined
366
- ? []
367
- : delta.deltaMessageReply.message.data.prng === undefined
368
- ? []
369
- : JSON.parse(delta.deltaMessageReply.message.data.prng);
370
- var m_id = mdata.map((u) => u.i);
371
- var m_offset = mdata.map((u) => u.o);
372
- var m_length = mdata.map((u) => u.l);
373
-
374
- var mentions = {};
375
-
376
- for (var i = 0; i < m_id.length; i++) {
377
- mentions[m_id[i]] = (
378
- delta.deltaMessageReply.message.body || ""
379
- ).substring(m_offset[i], m_offset[i] + m_length[i]);
380
- }
381
- //Mention block - 1#
382
- var callbackToReturn = {
383
- type: "message_reply",
384
- threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey
385
- .threadFbId
386
- ? delta.deltaMessageReply.message.messageMetadata.threadKey
387
- .threadFbId
388
- : delta.deltaMessageReply.message.messageMetadata.threadKey
389
- .otherUserFbId
390
- ).toString(),
391
- messageID:
392
- delta.deltaMessageReply.message.messageMetadata.messageId,
393
- senderID:
394
- delta.deltaMessageReply.message.messageMetadata.actorFbId.toString(),
395
- attachments: delta.deltaMessageReply.message.attachments
396
- .map(function (att) {
397
- var mercury = JSON.parse(att.mercuryJSON);
398
- Object.assign(att, mercury);
399
- return att;
400
- })
401
- .map((att) => {
402
- var x;
403
- try {
404
- x = utils._formatAttachment(att);
405
- } catch (ex) {
406
- x = att;
407
- x.error = ex;
408
- x.type = "unknown";
409
- }
410
- return x;
411
- }),
412
- args: (delta.deltaMessageReply.message.body || "")
413
- .trim()
414
- .split(/\s+/),
415
- body: delta.deltaMessageReply.message.body || "",
416
- mentions: mentions,
417
- timestamp:
418
- delta.deltaMessageReply.message.messageMetadata.timestamp,
419
- isGroup:
420
- !!delta.deltaMessageReply.message.messageMetadata.threadKey
421
- .threadFbId,
422
- participantIDs: delta.deltaMessageReply.message.participants?.map(
423
- (u) => u.toString(),
424
- ),
425
- };
426
-
427
- if (delta.deltaMessageReply.repliedToMessage) {
428
- //Mention block - #2
429
- mdata =
430
- delta.deltaMessageReply.repliedToMessage === undefined
431
- ? []
432
- : delta.deltaMessageReply.repliedToMessage.data === undefined
433
- ? []
434
- : delta.deltaMessageReply.repliedToMessage.data.prng ===
435
- undefined
436
- ? []
437
- : JSON.parse(
438
- delta.deltaMessageReply.repliedToMessage.data.prng,
439
- );
440
- m_id = mdata.map((u) => u.i);
441
- m_offset = mdata.map((u) => u.o);
442
- m_length = mdata.map((u) => u.l);
443
-
444
- var rmentions = {};
445
-
446
- for (var i = 0; i < m_id.length; i++) {
447
- rmentions[m_id[i]] = (
448
- delta.deltaMessageReply.repliedToMessage.body || ""
449
- ).substring(m_offset[i], m_offset[i] + m_length[i]);
450
- }
451
- //Mention block - 2#
452
- callbackToReturn.messageReply = {
453
- threadID: (delta.deltaMessageReply.repliedToMessage
454
- .messageMetadata.threadKey.threadFbId
455
- ? delta.deltaMessageReply.repliedToMessage.messageMetadata
456
- .threadKey.threadFbId
457
- : delta.deltaMessageReply.repliedToMessage.messageMetadata
458
- .threadKey.otherUserFbId
459
- ).toString(),
460
- messageID:
461
- delta.deltaMessageReply.repliedToMessage.messageMetadata
462
- .messageId,
463
- senderID:
464
- delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
465
- attachments: delta.deltaMessageReply.repliedToMessage.attachments
466
- .map(function (att) {
467
- var mercury = JSON.parse(att.mercuryJSON);
468
- Object.assign(att, mercury);
469
- return att;
470
- })
471
- .map((att) => {
472
- var x;
473
- try {
474
- x = utils._formatAttachment(att);
475
- } catch (ex) {
476
- x = att;
477
- x.error = ex;
478
- x.type = "unknown";
479
- }
480
- return x;
481
- }),
482
- args: (delta.deltaMessageReply.repliedToMessage.body || "")
483
- .trim()
484
- .split(/\s+/),
485
- body: delta.deltaMessageReply.repliedToMessage.body || "",
486
- isGroup:
487
- !!delta.deltaMessageReply.repliedToMessage.messageMetadata
488
- .threadKey.threadFbId,
489
- mentions: rmentions,
490
- timestamp:
491
- delta.deltaMessageReply.repliedToMessage.messageMetadata
492
- .timestamp,
493
- };
494
- } else if (delta.deltaMessageReply.replyToMessageId) {
495
- return defaultFuncs
496
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, {
497
- av: ctx.globalOptions.pageID,
498
- queries: JSON.stringify({
499
- o0: {
500
- //Using the same doc_id as forcedFetch
501
- doc_id: "2848441488556444",
502
- query_params: {
503
- thread_and_message_id: {
504
- thread_id: callbackToReturn.threadID,
505
- message_id: delta.deltaMessageReply.replyToMessageId.id,
506
- },
507
- },
508
- },
509
- }),
510
- })
511
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
512
- .then((resData) => {
513
- if (resData[resData.length - 1].error_results > 0) {
514
- throw resData[0].o0.errors;
515
- }
516
-
517
- if (resData[resData.length - 1].successful_results === 0) {
518
- throw {
519
- error: "forcedFetch: there was no successful_results",
520
- res: resData,
521
- };
522
- }
523
-
524
- var fetchData = resData[0].o0.data.message;
525
-
526
- var mobj = {};
527
- for (var n in fetchData.message.ranges) {
528
- mobj[fetchData.message.ranges[n].entity.id] = (
529
- fetchData.message.text || ""
530
- ).substr(
531
- fetchData.message.ranges[n].offset,
532
- fetchData.message.ranges[n].length,
533
- );
534
- }
535
-
536
- callbackToReturn.messageReply = {
537
- threadID: callbackToReturn.threadID,
538
- messageID: fetchData.message_id,
539
- senderID: fetchData.message_sender.id.toString(),
540
- attachments: fetchData.message.blob_attachment.map((att) => {
541
- var x;
542
- try {
543
- x = utils._formatAttachment({
544
- blob_attachment: att,
545
- });
546
- } catch (ex) {
547
- x = att;
548
- x.error = ex;
549
- x.type = "unknown";
550
- }
551
- return x;
552
- }),
553
- args: (delta.deltaMessageReply.repliedToMessage.body || "")
554
- .trim()
555
- .split(/\s+/),
556
- body: fetchData.message.text || "",
557
- isGroup: callbackToReturn.isGroup,
558
- mentions: mobj,
559
- timestamp: parseInt(fetchData.timestamp_precise),
560
- };
561
- })
562
- .catch((err) => {
563
- log.error("forcedFetch", err);
564
- })
565
- .finally(function () {
566
- if (ctx.globalOptions.autoMarkDelivery) {
567
- markDelivery(
568
- ctx,
569
- api,
570
- callbackToReturn.threadID,
571
- callbackToReturn.messageID,
572
- );
573
- }
574
- !ctx.globalOptions.selfListen &&
575
- callbackToReturn.senderID === ctx.userID
576
- ? undefined
577
- : (function () {
578
- globalCallback(null, callbackToReturn);
579
- })();
580
- });
581
- } else {
582
- callbackToReturn.delta = delta;
583
- }
584
-
585
- if (ctx.globalOptions.autoMarkDelivery) {
586
- markDelivery(
587
- ctx,
588
- api,
589
- callbackToReturn.threadID,
590
- callbackToReturn.messageID,
591
- );
592
- }
593
-
594
- return !ctx.globalOptions.selfListen &&
595
- callbackToReturn.senderID === ctx.userID
596
- ? undefined
597
- : (function () {
598
- globalCallback(null, callbackToReturn);
599
- })();
600
- }
601
- }
602
- return;
603
- }
604
- }
605
-
606
- if (v.delta.class !== "NewMessage" && !ctx.globalOptions.listenEvents) return;
607
-
608
- switch (v.delta.class) {
609
- case "ReadReceipt":
610
- var fmtMsg;
611
- try {
612
- fmtMsg = utils.formatDeltaReadReceipt(v.delta);
613
- } catch (err) {
614
- return globalCallback({
615
- error:
616
- "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
617
- detail: err,
618
- res: v.delta,
619
- type: "parse_error",
620
- });
621
- }
622
- return (function () {
623
- globalCallback(null, fmtMsg);
624
- })();
625
- case "AdminTextMessage":
626
- switch (v.delta.type) {
627
- case "change_thread_theme":
628
- // case "change_thread_icon": deprecated
629
- case "change_thread_quick_reaction":
630
- case "change_thread_nickname":
631
- case "change_thread_admins":
632
- case "change_thread_approval_mode":
633
- case "group_poll":
634
- case "messenger_call_log":
635
- case "participant_joined_group_call":
636
- var fmtMsg;
637
- try {
638
- fmtMsg = utils.formatDeltaEvent(v.delta);
639
- } catch (err) {
640
- return globalCallback({
641
- error:
642
- "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
643
- detail: err,
644
- res: v.delta,
645
- type: "parse_error",
646
- });
647
- }
648
- return (function () {
649
- globalCallback(null, fmtMsg);
650
- })();
651
- default:
652
- return;
653
- }
654
- break;
655
- //For group images
656
- case "ForcedFetch":
657
- if (!v.delta.threadKey) return;
658
- var mid = v.delta.messageId;
659
- var tid = v.delta.threadKey.threadFbId;
660
- if (mid && tid) {
661
- const form = {
662
- av: ctx.globalOptions.pageID,
663
- queries: JSON.stringify({
664
- o0: {
665
- //This doc_id is valid as of March 25, 2020
666
- doc_id: "2848441488556444",
667
- query_params: {
668
- thread_and_message_id: {
669
- thread_id: tid.toString(),
670
- message_id: mid,
671
- },
672
- },
673
- },
674
- }),
675
- };
676
-
677
- defaultFuncs
678
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
679
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
680
- .then((resData) => {
681
- if (resData[resData.length - 1].error_results > 0) {
682
- throw resData[0].o0.errors;
683
- }
684
-
685
- if (resData[resData.length - 1].successful_results === 0) {
686
- throw {
687
- error: "forcedFetch: there was no successful_results",
688
- res: resData,
689
- };
690
- }
691
-
692
- var fetchData = resData[0].o0.data.message;
693
-
694
- if (utils.getType(fetchData) == "Object") {
695
- log.info("forcedFetch", fetchData);
696
- switch (fetchData.__typename) {
697
- case "ThreadImageMessage":
698
- (!ctx.globalOptions.selfListen &&
699
- fetchData.message_sender.id.toString() === ctx.userID) ||
700
- !ctx.loggedIn
701
- ? undefined
702
- : (function () {
703
- globalCallback(null, {
704
- type: "event",
705
- threadID: utils.formatID(tid.toString()),
706
- logMessageType: "log:thread-image",
707
- logMessageData: {
708
- image: {
709
- attachmentID:
710
- fetchData.image_with_metadata &&
711
- fetchData.image_with_metadata
712
- .legacy_attachment_id,
713
- width:
714
- fetchData.image_with_metadata &&
715
- fetchData.image_with_metadata
716
- .original_dimensions.x,
717
- height:
718
- fetchData.image_with_metadata &&
719
- fetchData.image_with_metadata
720
- .original_dimensions.y,
721
- url:
722
- fetchData.image_with_metadata &&
723
- fetchData.image_with_metadata.preview.uri,
724
- },
725
- },
726
- logMessageBody: fetchData.snippet,
727
- timestamp: fetchData.timestamp_precise,
728
- author: fetchData.message_sender.id,
729
- });
730
- })();
731
- break;
732
- case "UserMessage":
733
- log.info("ff-Return", {
734
- type: "message",
735
- senderID: utils.formatID(fetchData.message_sender.id),
736
- body: fetchData.message.text || "",
737
- threadID: utils.formatID(tid.toString()),
738
- messageID: fetchData.message_id,
739
- attachments: [
740
- {
741
- type: "share",
742
- ID: fetchData.extensible_attachment
743
- .legacy_attachment_id,
744
- url: fetchData.extensible_attachment.story_attachment
745
- .url,
746
-
747
- title:
748
- fetchData.extensible_attachment.story_attachment
749
- .title_with_entities.text,
750
- description:
751
- fetchData.extensible_attachment.story_attachment
752
- .description.text,
753
- source:
754
- fetchData.extensible_attachment.story_attachment
755
- .source,
756
-
757
- image: (
758
- (
759
- fetchData.extensible_attachment.story_attachment
760
- .media || {}
761
- ).image || {}
762
- ).uri,
763
- width: (
764
- (
765
- fetchData.extensible_attachment.story_attachment
766
- .media || {}
767
- ).image || {}
768
- ).width,
769
- height: (
770
- (
771
- fetchData.extensible_attachment.story_attachment
772
- .media || {}
773
- ).image || {}
774
- ).height,
775
- playable:
776
- (
777
- fetchData.extensible_attachment.story_attachment
778
- .media || {}
779
- ).is_playable || false,
780
- duration:
781
- (
782
- fetchData.extensible_attachment.story_attachment
783
- .media || {}
784
- ).playable_duration_in_ms || 0,
785
-
786
- subattachments:
787
- fetchData.extensible_attachment.subattachments,
788
- properties:
789
- fetchData.extensible_attachment.story_attachment
790
- .properties,
791
- },
792
- ],
793
- mentions: {},
794
- timestamp: parseInt(fetchData.timestamp_precise),
795
- isGroup: fetchData.message_sender.id != tid.toString(),
796
- });
797
- globalCallback(null, {
798
- type: "message",
799
- senderID: utils.formatID(fetchData.message_sender.id),
800
- body: fetchData.message.text || "",
801
- threadID: utils.formatID(tid.toString()),
802
- messageID: fetchData.message_id,
803
- attachments: [
804
- {
805
- type: "share",
806
- ID: fetchData.extensible_attachment
807
- .legacy_attachment_id,
808
- url: fetchData.extensible_attachment.story_attachment
809
- .url,
810
-
811
- title:
812
- fetchData.extensible_attachment.story_attachment
813
- .title_with_entities.text,
814
- description:
815
- fetchData.extensible_attachment.story_attachment
816
- .description.text,
817
- source:
818
- fetchData.extensible_attachment.story_attachment
819
- .source,
820
-
821
- image: (
822
- (
823
- fetchData.extensible_attachment.story_attachment
824
- .media || {}
825
- ).image || {}
826
- ).uri,
827
- width: (
828
- (
829
- fetchData.extensible_attachment.story_attachment
830
- .media || {}
831
- ).image || {}
832
- ).width,
833
- height: (
834
- (
835
- fetchData.extensible_attachment.story_attachment
836
- .media || {}
837
- ).image || {}
838
- ).height,
839
- playable:
840
- (
841
- fetchData.extensible_attachment.story_attachment
842
- .media || {}
843
- ).is_playable || false,
844
- duration:
845
- (
846
- fetchData.extensible_attachment.story_attachment
847
- .media || {}
848
- ).playable_duration_in_ms || 0,
849
-
850
- subattachments:
851
- fetchData.extensible_attachment.subattachments,
852
- properties:
853
- fetchData.extensible_attachment.story_attachment
854
- .properties,
855
- },
856
- ],
857
- mentions: {},
858
- timestamp: parseInt(fetchData.timestamp_precise),
859
- isGroup: fetchData.message_sender.id != tid.toString(),
860
- });
861
- }
862
- } else {
863
- log.error("forcedFetch", fetchData);
864
- }
865
- })
866
- .catch((err) => {
867
- log.error("forcedFetch", err);
868
- });
869
- }
870
- break;
871
- case "ThreadName":
872
- case "ParticipantsAddedToGroupThread":
873
- case "ParticipantLeftGroupThread":
874
- var formattedEvent;
875
- try {
876
- formattedEvent = utils.formatDeltaEvent(v.delta);
877
- } catch (err) {
878
- return globalCallback({
879
- error:
880
- "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
881
- detail: err,
882
- res: v.delta,
883
- type: "parse_error",
884
- });
885
- }
886
- return (!ctx.globalOptions.selfListen &&
887
- formattedEvent.author.toString() === ctx.userID) ||
888
- !ctx.loggedIn
889
- ? undefined
890
- : (function () {
891
- globalCallback(null, formattedEvent);
892
- })();
893
- }
894
- }
895
-
896
- function markDelivery(ctx, api, threadID, messageID) {
897
- if (threadID && messageID) {
898
- api.markAsDelivered(threadID, messageID, (err) => {
899
- if (err) {
900
- log.error("markAsDelivered", err);
901
- } else {
902
- if (ctx.globalOptions.autoMarkRead) {
903
- api.markAsRead(threadID, (err) => {
904
- if (err) {
905
- log.error("markAsDelivered", err);
906
- }
907
- });
908
- }
909
- }
910
- });
911
- }
912
- }
913
-
914
- module.exports = function (defaultFuncs, api, ctx) {
915
- var globalCallback = identity;
916
- getSeqID = function getSeqID() {
917
- ctx.t_mqttCalled = false;
918
- defaultFuncs
919
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
920
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
921
- .then((resData) => {
922
- if (utils.getType(resData) != "Array") {
923
- throw {
924
- error: "Not logged in",
925
- res: resData,
926
- };
927
- }
928
-
929
- if (resData && resData[resData.length - 1].error_results > 0) {
930
- throw resData[0].o0.errors;
931
- }
932
-
933
- if (resData[resData.length - 1].successful_results === 0) {
934
- throw {
935
- error: "getSeqId: there was no successful_results",
936
- res: resData,
937
- };
938
- }
939
-
940
- if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
941
- ctx.lastSeqId =
942
- resData[0].o0.data.viewer.message_threads.sync_sequence_id;
943
- listenMqtt(defaultFuncs, api, ctx, globalCallback);
944
- } else {
945
- throw {
946
- error: "getSeqId: no sync_sequence_id found.",
947
- res: resData,
948
- };
949
- }
950
- })
951
- .catch((err) => {
952
- log.error("getSeqId", err);
953
- if (utils.getType(err) == "Object" && err.error === "Not logged in") {
954
- ctx.loggedIn = false;
955
- }
956
- return globalCallback(err);
957
- });
958
- };
959
-
960
- return function (callback) {
961
- class MessageEmitter extends EventEmitter {
962
- stopListening(callback) {
963
- callback = callback || (() => {});
964
- globalCallback = identity;
965
- if (ctx.mqttClient) {
966
- ctx.mqttClient.unsubscribe("/webrtc");
967
- ctx.mqttClient.unsubscribe("/rtc_multi");
968
- ctx.mqttClient.unsubscribe("/onevc");
969
- ctx.mqttClient.publish("/browser_close", "{}");
970
- ctx.mqttClient.end(false, function (...data) {
971
- callback(data);
972
- ctx.mqttClient = undefined;
973
- });
974
- }
975
- }
976
- }
977
-
978
- var msgEmitter = new MessageEmitter();
979
- globalCallback =
980
- callback ||
981
- function (error, message) {
982
- if (error) {
983
- return msgEmitter.emit("error", error);
984
- }
985
- msgEmitter.emit("message", message);
986
- };
987
-
988
- //Reset some stuff
989
- if (!ctx.firstListen) ctx.lastSeqId = null;
990
- ctx.syncToken = undefined;
991
- ctx.t_mqttCalled = false;
992
-
993
- //Same request as getThreadList
994
- form = {
995
- av: ctx.globalOptions.pageID,
996
- queries: JSON.stringify({
997
- o0: {
998
- doc_id: "3336396659757871",
999
- query_params: {
1000
- limit: 1,
1001
- before: null,
1002
- tags: ["INBOX"],
1003
- includeDeliveryReceipts: false,
1004
- includeSeqID: true,
1005
- },
1006
- },
1007
- }),
1008
- };
1009
-
1010
- if (!ctx.firstListen || !ctx.lastSeqId) {
1011
- getSeqID();
1012
- } else {
1013
- listenMqtt(defaultFuncs, api, ctx, globalCallback);
1014
- }
1015
- ctx.firstListen = false;
1016
- return msgEmitter;
1017
- };
1018
- };