toru-fca 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +319 -0
  3. package/advancedSystem.js +95 -0
  4. package/build/messagix.dll +0 -0
  5. package/build/messagix.so +0 -0
  6. package/checkUpdate.js +37 -0
  7. package/config.json +45 -0
  8. package/e2ee.js +719 -0
  9. package/index.js +715 -0
  10. package/lib/index.mjs +1412 -0
  11. package/package.json +69 -0
  12. package/src/OldMessage.js +357 -0
  13. package/src/addExternalModule.js +25 -0
  14. package/src/addUserToGroup.js +117 -0
  15. package/src/changeAdminStatus.js +105 -0
  16. package/src/changeArchivedStatus.js +57 -0
  17. package/src/changeAvatar.js +138 -0
  18. package/src/changeAvatarV2.js +86 -0
  19. package/src/changeAvt.js +85 -0
  20. package/src/changeBio.js +78 -0
  21. package/src/changeBlockedStatus.js +51 -0
  22. package/src/changeBlockedStatusMqtt.js +80 -0
  23. package/src/changeCover.js +72 -0
  24. package/src/changeGroupImage.js +137 -0
  25. package/src/changeName.js +79 -0
  26. package/src/changeNickname.js +61 -0
  27. package/src/changeThreadColor.js +67 -0
  28. package/src/changeThreadEmoji.js +57 -0
  29. package/src/changeUsername.js +59 -0
  30. package/src/createCommentPost.js +230 -0
  31. package/src/createNewGroup.js +90 -0
  32. package/src/createPoll.js +73 -0
  33. package/src/createPost.js +276 -0
  34. package/src/data/getThreadInfo.json +1 -0
  35. package/src/deleteMessage.js +58 -0
  36. package/src/deleteThread.js +58 -0
  37. package/src/editMessage.js +81 -0
  38. package/src/editMessageOld.js +67 -0
  39. package/src/follow.js +74 -0
  40. package/src/forwardAttachment.js +62 -0
  41. package/src/friendList.js +104 -0
  42. package/src/getAccess.js +112 -0
  43. package/src/getAvatarUser.js +78 -0
  44. package/src/getBotInitialData.js +42 -0
  45. package/src/getCtx.js +5 -0
  46. package/src/getCurrentUserID.js +7 -0
  47. package/src/getEmojiUrl.js +29 -0
  48. package/src/getFriendsList.js +85 -0
  49. package/src/getMessage.js +849 -0
  50. package/src/getOptions.js +5 -0
  51. package/src/getRegion.js +7 -0
  52. package/src/getThreadHistory.js +682 -0
  53. package/src/getThreadHistoryDeprecated.js +71 -0
  54. package/src/getThreadInfo.js +232 -0
  55. package/src/getThreadInfoDeprecated.js +56 -0
  56. package/src/getThreadList.js +213 -0
  57. package/src/getThreadListDeprecated.js +46 -0
  58. package/src/getThreadPictures.js +59 -0
  59. package/src/getThreadTheme.js +81 -0
  60. package/src/getUID.js +119 -0
  61. package/src/getUserID.js +61 -0
  62. package/src/getUserInfo.js +66 -0
  63. package/src/handleFriendRequest.js +46 -0
  64. package/src/handleMessageRequest.js +47 -0
  65. package/src/httpGet.js +49 -0
  66. package/src/httpPost.js +48 -0
  67. package/src/httpPostFormData.js +70 -0
  68. package/src/listenMqtt.js +955 -0
  69. package/src/listenNotification.js +85 -0
  70. package/src/logout.js +19 -0
  71. package/src/markAsDelivered.js +47 -0
  72. package/src/markAsRead.js +72 -0
  73. package/src/markAsReadAll.js +40 -0
  74. package/src/markAsSeen.js +48 -0
  75. package/src/metaTheme.js +189 -0
  76. package/src/muteThread.js +45 -0
  77. package/src/note.js +228 -0
  78. package/src/pinMessage.js +59 -0
  79. package/src/refreshFb_dtsg.js +91 -0
  80. package/src/removeSuspiciousAccount.js +78 -0
  81. package/src/removeUserFromGroup.js +81 -0
  82. package/src/reply.js +442 -0
  83. package/src/resolvePhotoUrl.js +47 -0
  84. package/src/searchForThread.js +53 -0
  85. package/src/searchFriends.js +140 -0
  86. package/src/searchStickers.js +53 -0
  87. package/src/send.js +46 -0
  88. package/src/sendButtons.js +163 -0
  89. package/src/sendComment.js +159 -0
  90. package/src/sendFriendRequest.js +112 -0
  91. package/src/sendMessage.js +440 -0
  92. package/src/sendMessageMqtt.js +323 -0
  93. package/src/sendTypingIndicator.js +54 -0
  94. package/src/setActiveStatus.js +92 -0
  95. package/src/setMessageReaction.js +149 -0
  96. package/src/setMessageReactionMqtt.js +62 -0
  97. package/src/setPostReaction.js +114 -0
  98. package/src/setProfileGuard.js +44 -0
  99. package/src/setProfileLock.js +97 -0
  100. package/src/setStoryReaction.js +133 -0
  101. package/src/setStorySeen.js +108 -0
  102. package/src/setThreadTheme.js +102 -0
  103. package/src/setTitle.js +92 -0
  104. package/src/shareContact.js +110 -0
  105. package/src/shareLink.js +59 -0
  106. package/src/stopListenMqtt.js +37 -0
  107. package/src/storyManager.js +357 -0
  108. package/src/suggestFriend.js +132 -0
  109. package/src/threadColors.js +131 -0
  110. package/src/unfriend.js +54 -0
  111. package/src/unsendMessage.js +68 -0
  112. package/src/uploadAttachment.js +115 -0
  113. package/utils.js +3044 -0
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ module.exports = function (defaultFuncs, api, ctx) {
4
+ return (str) => ctx.globalOptions[str];
5
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ module.exports = function (defaultFuncs, api, ctx) {
4
+ return function getRegion() {
5
+ return ctx?.region;
6
+ };
7
+ };
@@ -0,0 +1,682 @@
1
+ "use strict";
2
+
3
+ var log = require("npmlog");
4
+
5
+ const utils = require("../utils");
6
+ // @NethWs3Dev
7
+
8
+ function getExtension(original_extension, filename = "") {
9
+ if (original_extension) {
10
+ return original_extension;
11
+ } else {
12
+ const extension = filename.split(".").pop();
13
+ if (extension === filename) {
14
+ return "";
15
+ } else {
16
+ return extension;
17
+ }
18
+ }
19
+ }
20
+
21
+ function formatAttachmentsGraphQLResponse(attachment) {
22
+ switch (attachment.__typename) {
23
+ case "MessageImage":
24
+ return {
25
+ type: "photo",
26
+ ID: attachment.legacy_attachment_id,
27
+ filename: attachment.filename,
28
+ original_extension: getExtension(
29
+ attachment.original_extension,
30
+ attachment.filename,
31
+ ),
32
+ thumbnailUrl: attachment.thumbnail.uri,
33
+
34
+ previewUrl: attachment.preview.uri,
35
+ previewWidth: attachment.preview.width,
36
+ previewHeight: attachment.preview.height,
37
+
38
+ largePreviewUrl: attachment.large_preview.uri,
39
+ largePreviewHeight: attachment.large_preview.height,
40
+ largePreviewWidth: attachment.large_preview.width,
41
+
42
+ // You have to query for the real image. See below.
43
+ url: attachment.large_preview.uri, // @Legacy
44
+ width: attachment.large_preview.width, // @Legacy
45
+ height: attachment.large_preview.height, // @Legacy
46
+ name: attachment.filename, // @Legacy
47
+
48
+ // @Undocumented
49
+ attributionApp: attachment.attribution_app
50
+ ? {
51
+ attributionAppID: attachment.attribution_app.id,
52
+ name: attachment.attribution_app.name,
53
+ logo: attachment.attribution_app.square_logo,
54
+ }
55
+ : null,
56
+
57
+ // @TODO No idea what this is, should we expose it?
58
+ // Ben - July 15th 2017
59
+ // renderAsSticker: attachment.render_as_sticker,
60
+
61
+ // This is _not_ the real URI, this is still just a large preview.
62
+ // To get the URL we'll need to support a POST query to
63
+ //
64
+ // https://www.facebook.com/webgraphql/query/
65
+ //
66
+ // With the following query params:
67
+ //
68
+ // query_id:728987990612546
69
+ // variables:{"id":"100009069356507","photoID":"10213724771692996"}
70
+ // dpr:1
71
+ //
72
+ // No special form though.
73
+ };
74
+ case "MessageAnimatedImage":
75
+ return {
76
+ type: "animated_image",
77
+ ID: attachment.legacy_attachment_id,
78
+ filename: attachment.filename,
79
+ original_extension: getExtension(
80
+ attachment.original_extension,
81
+ attachment.filename,
82
+ ),
83
+
84
+ previewUrl: attachment.preview_image.uri,
85
+ previewWidth: attachment.preview_image.width,
86
+ previewHeight: attachment.preview_image.height,
87
+
88
+ url: attachment.animated_image.uri,
89
+ width: attachment.animated_image.width,
90
+ height: attachment.animated_image.height,
91
+
92
+ thumbnailUrl: attachment.preview_image.uri, // @Legacy
93
+ name: attachment.filename, // @Legacy
94
+ facebookUrl: attachment.animated_image.uri, // @Legacy
95
+ rawGifImage: attachment.animated_image.uri, // @Legacy
96
+ animatedGifUrl: attachment.animated_image.uri, // @Legacy
97
+ animatedGifPreviewUrl: attachment.preview_image.uri, // @Legacy
98
+ animatedWebpUrl: attachment.animated_image.uri, // @Legacy
99
+ animatedWebpPreviewUrl: attachment.preview_image.uri, // @Legacy
100
+
101
+ // @Undocumented
102
+ attributionApp: attachment.attribution_app
103
+ ? {
104
+ attributionAppID: attachment.attribution_app.id,
105
+ name: attachment.attribution_app.name,
106
+ logo: attachment.attribution_app.square_logo,
107
+ }
108
+ : null,
109
+ };
110
+ case "MessageVideo":
111
+ return {
112
+ type: "video",
113
+ ID: attachment.legacy_attachment_id,
114
+ filename: attachment.filename,
115
+ original_extension: getExtension(
116
+ attachment.original_extension,
117
+ attachment.filename,
118
+ ),
119
+ duration: attachment.playable_duration_in_ms,
120
+
121
+ thumbnailUrl: attachment.large_image.uri, // @Legacy
122
+
123
+ previewUrl: attachment.large_image.uri,
124
+ previewWidth: attachment.large_image.width,
125
+ previewHeight: attachment.large_image.height,
126
+
127
+ url: attachment.playable_url,
128
+ width: attachment.original_dimensions.x,
129
+ height: attachment.original_dimensions.y,
130
+
131
+ videoType: attachment.video_type.toLowerCase(),
132
+ };
133
+ case "MessageFile":
134
+ return {
135
+ type: "file",
136
+ ID: attachment.message_file_fbid,
137
+ filename: attachment.filename,
138
+ original_extension: getExtension(
139
+ attachment.original_extension,
140
+ attachment.filename,
141
+ ),
142
+
143
+ url: attachment.url,
144
+ isMalicious: attachment.is_malicious,
145
+ contentType: attachment.content_type,
146
+
147
+ name: attachment.filename, // @Legacy
148
+ mimeType: "", // @Legacy
149
+ fileSize: -1, // @Legacy
150
+ };
151
+ case "MessageAudio":
152
+ return {
153
+ type: "audio",
154
+ ID: attachment.url_shimhash, // Not fowardable
155
+ filename: attachment.filename,
156
+ original_extension: getExtension(
157
+ attachment.original_extension,
158
+ attachment.filename,
159
+ ),
160
+
161
+ duration: attachment.playable_duration_in_ms,
162
+ audioType: attachment.audio_type,
163
+ url: attachment.playable_url,
164
+
165
+ isVoiceMail: attachment.is_voicemail,
166
+ };
167
+ default:
168
+ return {
169
+ error: "Don't know about attachment type " + attachment.__typename,
170
+ };
171
+ }
172
+ }
173
+
174
+ function formatExtensibleAttachment(attachment) {
175
+ if (attachment.story_attachment) {
176
+ return {
177
+ type: "share",
178
+ ID: attachment.legacy_attachment_id,
179
+ url: attachment.story_attachment.url,
180
+
181
+ title: attachment.story_attachment.title_with_entities.text,
182
+ description:
183
+ attachment.story_attachment.description &&
184
+ attachment.story_attachment.description.text,
185
+ source:
186
+ attachment.story_attachment.source == null
187
+ ? null
188
+ : attachment.story_attachment.source.text,
189
+
190
+ image:
191
+ attachment.story_attachment.media == null
192
+ ? null
193
+ : attachment.story_attachment.media.animated_image == null &&
194
+ attachment.story_attachment.media.image == null
195
+ ? null
196
+ : (
197
+ attachment.story_attachment.media.animated_image ||
198
+ attachment.story_attachment.media.image
199
+ ).uri,
200
+ width:
201
+ attachment.story_attachment.media == null
202
+ ? null
203
+ : attachment.story_attachment.media.animated_image == null &&
204
+ attachment.story_attachment.media.image == null
205
+ ? null
206
+ : (
207
+ attachment.story_attachment.media.animated_image ||
208
+ attachment.story_attachment.media.image
209
+ ).width,
210
+ height:
211
+ attachment.story_attachment.media == null
212
+ ? null
213
+ : attachment.story_attachment.media.animated_image == null &&
214
+ attachment.story_attachment.media.image == null
215
+ ? null
216
+ : (
217
+ attachment.story_attachment.media.animated_image ||
218
+ attachment.story_attachment.media.image
219
+ ).height,
220
+ playable:
221
+ attachment.story_attachment.media == null
222
+ ? null
223
+ : attachment.story_attachment.media.is_playable,
224
+ duration:
225
+ attachment.story_attachment.media == null
226
+ ? null
227
+ : attachment.story_attachment.media.playable_duration_in_ms,
228
+ playableUrl:
229
+ attachment.story_attachment.media == null
230
+ ? null
231
+ : attachment.story_attachment.media.playable_url,
232
+
233
+ subattachments: attachment.story_attachment.subattachments,
234
+
235
+ // Format example:
236
+ //
237
+ // [{
238
+ // key: "width",
239
+ // value: { text: "1280" }
240
+ // }]
241
+ //
242
+ // That we turn into:
243
+ //
244
+ // {
245
+ // width: "1280"
246
+ // }
247
+ //
248
+ properties: attachment.story_attachment.properties.reduce(function (
249
+ obj,
250
+ cur,
251
+ ) {
252
+ obj[cur.key] = cur.value.text;
253
+ return obj;
254
+ }, {}),
255
+
256
+ // Deprecated fields
257
+ animatedImageSize: "", // @Legacy
258
+ facebookUrl: "", // @Legacy
259
+ styleList: "", // @Legacy
260
+ target: "", // @Legacy
261
+ thumbnailUrl:
262
+ attachment.story_attachment.media == null
263
+ ? null
264
+ : attachment.story_attachment.media.animated_image == null &&
265
+ attachment.story_attachment.media.image == null
266
+ ? null
267
+ : (
268
+ attachment.story_attachment.media.animated_image ||
269
+ attachment.story_attachment.media.image
270
+ ).uri, // @Legacy
271
+ thumbnailWidth:
272
+ attachment.story_attachment.media == null
273
+ ? null
274
+ : attachment.story_attachment.media.animated_image == null &&
275
+ attachment.story_attachment.media.image == null
276
+ ? null
277
+ : (
278
+ attachment.story_attachment.media.animated_image ||
279
+ attachment.story_attachment.media.image
280
+ ).width, // @Legacy
281
+ thumbnailHeight:
282
+ attachment.story_attachment.media == null
283
+ ? null
284
+ : attachment.story_attachment.media.animated_image == null &&
285
+ attachment.story_attachment.media.image == null
286
+ ? null
287
+ : (
288
+ attachment.story_attachment.media.animated_image ||
289
+ attachment.story_attachment.media.image
290
+ ).height, // @Legacy
291
+ };
292
+ } else {
293
+ return { error: "Don't know what to do with extensible_attachment." };
294
+ }
295
+ }
296
+
297
+ function formatReactionsGraphQL(reaction) {
298
+ return {
299
+ reaction: reaction.reaction,
300
+ userID: reaction.user.id,
301
+ };
302
+ }
303
+
304
+ function formatEventData(event) {
305
+ if (event == null) {
306
+ return {};
307
+ }
308
+
309
+ switch (event.__typename) {
310
+ case "ThemeColorExtensibleMessageAdminText":
311
+ return {
312
+ color: event.theme_color,
313
+ };
314
+ case "ThreadNicknameExtensibleMessageAdminText":
315
+ return {
316
+ nickname: event.nickname,
317
+ participantID: event.participant_id,
318
+ };
319
+ case "ThreadIconExtensibleMessageAdminText":
320
+ return {
321
+ threadIcon: event.thread_icon,
322
+ };
323
+ case "InstantGameUpdateExtensibleMessageAdminText":
324
+ return {
325
+ gameID: event.game == null ? null : event.game.id,
326
+ update_type: event.update_type,
327
+ collapsed_text: event.collapsed_text,
328
+ expanded_text: event.expanded_text,
329
+ instant_game_update_data: event.instant_game_update_data,
330
+ };
331
+ case "GameScoreExtensibleMessageAdminText":
332
+ return {
333
+ game_type: event.game_type,
334
+ };
335
+ case "RtcCallLogExtensibleMessageAdminText":
336
+ return {
337
+ event: event.event,
338
+ is_video_call: event.is_video_call,
339
+ server_info_data: event.server_info_data,
340
+ };
341
+ case "GroupPollExtensibleMessageAdminText":
342
+ return {
343
+ event_type: event.event_type,
344
+ total_count: event.total_count,
345
+ question: event.question,
346
+ };
347
+ case "AcceptPendingThreadExtensibleMessageAdminText":
348
+ return {
349
+ accepter_id: event.accepter_id,
350
+ requester_id: event.requester_id,
351
+ };
352
+ case "ConfirmFriendRequestExtensibleMessageAdminText":
353
+ return {
354
+ friend_request_recipient: event.friend_request_recipient,
355
+ friend_request_sender: event.friend_request_sender,
356
+ };
357
+ case "AddContactExtensibleMessageAdminText":
358
+ return {
359
+ contact_added_id: event.contact_added_id,
360
+ contact_adder_id: event.contact_adder_id,
361
+ };
362
+ case "AdExtensibleMessageAdminText":
363
+ return {
364
+ ad_client_token: event.ad_client_token,
365
+ ad_id: event.ad_id,
366
+ ad_preferences_link: event.ad_preferences_link,
367
+ ad_properties: event.ad_properties,
368
+ };
369
+ // never data
370
+ case "ParticipantJoinedGroupCallExtensibleMessageAdminText":
371
+ case "ThreadEphemeralTtlModeExtensibleMessageAdminText":
372
+ case "StartedSharingVideoExtensibleMessageAdminText":
373
+ case "LightweightEventCreateExtensibleMessageAdminText":
374
+ case "LightweightEventNotifyExtensibleMessageAdminText":
375
+ case "LightweightEventNotifyBeforeEventExtensibleMessageAdminText":
376
+ case "LightweightEventUpdateTitleExtensibleMessageAdminText":
377
+ case "LightweightEventUpdateTimeExtensibleMessageAdminText":
378
+ case "LightweightEventUpdateLocationExtensibleMessageAdminText":
379
+ case "LightweightEventDeleteExtensibleMessageAdminText":
380
+ return {};
381
+ default:
382
+ return {
383
+ error: "Don't know what to with event data type " + event.__typename,
384
+ };
385
+ }
386
+ }
387
+
388
+ function formatMessagesGraphQLResponse(data) {
389
+ const messageThread = data.o0.data.message_thread;
390
+ const threadID = messageThread.thread_key.thread_fbid
391
+ ? messageThread.thread_key.thread_fbid
392
+ : messageThread.thread_key.other_user_id;
393
+
394
+ const messages = messageThread.messages.nodes.map(function (d) {
395
+ switch (d.__typename) {
396
+ case "UserMessage":
397
+ // Give priority to stickers. They're seen as normal messages but we've
398
+ // been considering them as attachments.
399
+ var maybeStickerAttachment;
400
+ if (d.sticker) {
401
+ maybeStickerAttachment = [
402
+ {
403
+ type: "sticker",
404
+ ID: d.sticker.id,
405
+ url: d.sticker.url,
406
+
407
+ packID: d.sticker.pack ? d.sticker.pack.id : null,
408
+ spriteUrl: d.sticker.sprite_image,
409
+ spriteUrl2x: d.sticker.sprite_image_2x,
410
+ width: d.sticker.width,
411
+ height: d.sticker.height,
412
+
413
+ caption: d.snippet, // Not sure what the heck caption was.
414
+ description: d.sticker.label, // Not sure about this one either.
415
+
416
+ frameCount: d.sticker.frame_count,
417
+ frameRate: d.sticker.frame_rate,
418
+ framesPerRow: d.sticker.frames_per_row,
419
+ framesPerCol: d.sticker.frames_per_col,
420
+
421
+ stickerID: d.sticker.id, // @Legacy
422
+ spriteURI: d.sticker.sprite_image, // @Legacy
423
+ spriteURI2x: d.sticker.sprite_image_2x, // @Legacy
424
+ },
425
+ ];
426
+ }
427
+
428
+ var mentionsObj = {};
429
+ if (d.message !== null) {
430
+ d.message.ranges.forEach((e) => {
431
+ mentionsObj[e.entity.id] = d.message.text.substr(
432
+ e.offset,
433
+ e.length,
434
+ );
435
+ });
436
+ }
437
+
438
+ return {
439
+ type: "message",
440
+ attachments: maybeStickerAttachment
441
+ ? maybeStickerAttachment
442
+ : d.blob_attachments && d.blob_attachments.length > 0
443
+ ? d.blob_attachments.map(formatAttachmentsGraphQLResponse)
444
+ : d.extensible_attachment
445
+ ? [formatExtensibleAttachment(d.extensible_attachment)]
446
+ : [],
447
+ body: d.message !== null ? d.message.text : "",
448
+ isGroup: messageThread.thread_type === "GROUP",
449
+ messageID: d.message_id,
450
+ senderID: d.message_sender.id,
451
+ threadID: threadID,
452
+ timestamp: d.timestamp_precise,
453
+
454
+ mentions: mentionsObj,
455
+ isUnread: d.unread,
456
+
457
+ // New
458
+ messageReactions: d.message_reactions
459
+ ? d.message_reactions.map(formatReactionsGraphQL)
460
+ : null,
461
+ isSponsored: d.is_sponsored,
462
+ snippet: d.snippet,
463
+ };
464
+ case "ThreadNameMessage":
465
+ return {
466
+ type: "event",
467
+ messageID: d.message_id,
468
+ threadID: threadID,
469
+ isGroup: messageThread.thread_type === "GROUP",
470
+ senderID: d.message_sender.id,
471
+ timestamp: d.timestamp_precise,
472
+ eventType: "change_thread_name",
473
+ snippet: d.snippet,
474
+ eventData: {
475
+ threadName: d.thread_name,
476
+ },
477
+
478
+ // @Legacy
479
+ author: d.message_sender.id,
480
+ logMessageType: "log:thread-name",
481
+ logMessageData: { name: d.thread_name },
482
+ };
483
+ case "ThreadImageMessage":
484
+ return {
485
+ type: "event",
486
+ messageID: d.message_id,
487
+ threadID: threadID,
488
+ isGroup: messageThread.thread_type === "GROUP",
489
+ senderID: d.message_sender.id,
490
+ timestamp: d.timestamp_precise,
491
+ eventType: "change_thread_image",
492
+ snippet: d.snippet,
493
+ eventData:
494
+ d.image_with_metadata == null
495
+ ? {} /* removed image */
496
+ : {
497
+ /* image added */
498
+ threadImage: {
499
+ attachmentID: d.image_with_metadata.legacy_attachment_id,
500
+ width: d.image_with_metadata.original_dimensions.x,
501
+ height: d.image_with_metadata.original_dimensions.y,
502
+ url: d.image_with_metadata.preview.uri,
503
+ },
504
+ },
505
+
506
+ // @Legacy
507
+ logMessageType: "log:thread-icon",
508
+ logMessageData: {
509
+ thread_icon: d.image_with_metadata
510
+ ? d.image_with_metadata.preview.uri
511
+ : null,
512
+ },
513
+ };
514
+ case "ParticipantLeftMessage":
515
+ return {
516
+ type: "event",
517
+ messageID: d.message_id,
518
+ threadID: threadID,
519
+ isGroup: messageThread.thread_type === "GROUP",
520
+ senderID: d.message_sender.id,
521
+ timestamp: d.timestamp_precise,
522
+ eventType: "remove_participants",
523
+ snippet: d.snippet,
524
+ eventData: {
525
+ // Array of IDs.
526
+ participantsRemoved: d.participants_removed.map(function (p) {
527
+ return p.id;
528
+ }),
529
+ },
530
+
531
+ // @Legacy
532
+ logMessageType: "log:unsubscribe",
533
+ logMessageData: {
534
+ leftParticipantFbId: d.participants_removed.map(function (p) {
535
+ return p.id;
536
+ }),
537
+ },
538
+ };
539
+ case "ParticipantsAddedMessage":
540
+ return {
541
+ type: "event",
542
+ messageID: d.message_id,
543
+ threadID: threadID,
544
+ isGroup: messageThread.thread_type === "GROUP",
545
+ senderID: d.message_sender.id,
546
+ timestamp: d.timestamp_precise,
547
+ eventType: "add_participants",
548
+ snippet: d.snippet,
549
+ eventData: {
550
+ // Array of IDs.
551
+ participantsAdded: d.participants_added.map(function (p) {
552
+ return p.id;
553
+ }),
554
+ },
555
+
556
+ // @Legacy
557
+ logMessageType: "log:subscribe",
558
+ logMessageData: {
559
+ addedParticipants: d.participants_added.map(function (p) {
560
+ return p.id;
561
+ }),
562
+ },
563
+ };
564
+ case "VideoCallMessage":
565
+ return {
566
+ type: "event",
567
+ messageID: d.message_id,
568
+ threadID: threadID,
569
+ isGroup: messageThread.thread_type === "GROUP",
570
+ senderID: d.message_sender.id,
571
+ timestamp: d.timestamp_precise,
572
+ eventType: "video_call",
573
+ snippet: d.snippet,
574
+
575
+ // @Legacy
576
+ logMessageType: "other",
577
+ };
578
+ case "VoiceCallMessage":
579
+ return {
580
+ type: "event",
581
+ messageID: d.message_id,
582
+ threadID: threadID,
583
+ isGroup: messageThread.thread_type === "GROUP",
584
+ senderID: d.message_sender.id,
585
+ timestamp: d.timestamp_precise,
586
+ eventType: "voice_call",
587
+ snippet: d.snippet,
588
+
589
+ // @Legacy
590
+ logMessageType: "other",
591
+ };
592
+ case "GenericAdminTextMessage":
593
+ return {
594
+ type: "event",
595
+ messageID: d.message_id,
596
+ threadID: threadID,
597
+ isGroup: messageThread.thread_type === "GROUP",
598
+ senderID: d.message_sender.id,
599
+ timestamp: d.timestamp_precise,
600
+ snippet: d.snippet,
601
+ eventType: d.extensible_message_admin_text_type.toLowerCase(),
602
+ eventData: formatEventData(d.extensible_message_admin_text),
603
+
604
+ // @Legacy
605
+ logMessageType: utils.getAdminTextMessageType(
606
+ d.extensible_message_admin_text_type,
607
+ ),
608
+ logMessageData: d.extensible_message_admin_text, // Maybe different?
609
+ };
610
+ default:
611
+ return { error: "Don't know about message type " + d.__typename };
612
+ }
613
+ });
614
+ return messages;
615
+ }
616
+
617
+ module.exports = function (defaultFuncs, api, ctx) {
618
+ return function getThreadHistoryGraphQL(
619
+ threadID,
620
+ amount,
621
+ timestamp,
622
+ callback,
623
+ ) {
624
+ let resolveFunc = function () {};
625
+ let rejectFunc = function () {};
626
+ const returnPromise = new Promise(function (resolve, reject) {
627
+ resolveFunc = resolve;
628
+ rejectFunc = reject;
629
+ });
630
+
631
+ if (!callback) {
632
+ callback = function (err, data) {
633
+ if (err) {
634
+ return rejectFunc(err);
635
+ }
636
+ resolveFunc(data);
637
+ };
638
+ }
639
+
640
+ // `queries` has to be a string. I couldn't tell from the dev console. This
641
+ // took me a really long time to figure out. I deserve a cookie for this.
642
+ const form = {
643
+ av: ctx.globalOptions.pageID,
644
+ queries: JSON.stringify({
645
+ o0: {
646
+ // This doc_id was valid on February 2nd 2017.
647
+ doc_id: "1498317363570230",
648
+ query_params: {
649
+ id: threadID,
650
+ message_limit: amount,
651
+ load_messages: 1,
652
+ load_read_receipts: false,
653
+ before: timestamp,
654
+ },
655
+ },
656
+ }),
657
+ };
658
+
659
+ defaultFuncs
660
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
661
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
662
+ .then(function (resData) {
663
+ if (resData.error) {
664
+ throw resData;
665
+ }
666
+ // This returns us an array of things. The last one is the success /
667
+ // failure one.
668
+ // @TODO What do we do in this case?
669
+ if (resData[resData.length - 1].error_results !== 0) {
670
+ throw new Error("There was an error_result.");
671
+ }
672
+
673
+ callback(null, formatMessagesGraphQLResponse(resData[0]));
674
+ })
675
+ .catch(function (err) {
676
+ log.error("getThreadHistoryGraphQL", err);
677
+ return callback(err);
678
+ });
679
+
680
+ return returnPromise;
681
+ };
682
+ };