alicezetion 1.9.1 → 1.9.3

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