@cexy/hoonfca 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 (84) hide show
  1. package/README.md +83 -0
  2. package/index.js +467 -0
  3. package/package.json +12 -0
  4. package/replit.nix +3 -0
  5. package/src/addExternalModule.js +25 -0
  6. package/src/addUserToGroup.js +98 -0
  7. package/src/changeAdminStatus.js +98 -0
  8. package/src/changeArchivedStatus.js +51 -0
  9. package/src/changeAvatar.js +89 -0
  10. package/src/changeBio.js +74 -0
  11. package/src/changeBlockedStatus.js +45 -0
  12. package/src/changeBlockedStatusMqtt.js +65 -0
  13. package/src/changeCover.js +92 -0
  14. package/src/changeGroupImage.js +110 -0
  15. package/src/changeName.js +106 -0
  16. package/src/changeNickname.js +58 -0
  17. package/src/changeThreadColor.js +62 -0
  18. package/src/changeThreadEmoji.js +54 -0
  19. package/src/changeUsername.js +80 -0
  20. package/src/createCommentPost.js +196 -0
  21. package/src/createNewGroup.js +81 -0
  22. package/src/createPoll.js +64 -0
  23. package/src/createPost.js +285 -0
  24. package/src/data/getThreadInfo.json +1 -0
  25. package/src/deleteMessage.js +55 -0
  26. package/src/deleteThread.js +55 -0
  27. package/src/editMessage.js +66 -0
  28. package/src/follow.js +71 -0
  29. package/src/forwardAttachment.js +57 -0
  30. package/src/getAccess.js +130 -0
  31. package/src/getAvatarUser.js +88 -0
  32. package/src/getBotInitialData.js +59 -0
  33. package/src/getCtx.js +5 -0
  34. package/src/getCurrentUserID.js +5 -0
  35. package/src/getEmojiUrl.js +18 -0
  36. package/src/getFriendsList.js +81 -0
  37. package/src/getMessage.js +827 -0
  38. package/src/getOptions.js +5 -0
  39. package/src/getRegion.js +7 -0
  40. package/src/getThreadHistory.js +496 -0
  41. package/src/getThreadHistoryDeprecated.js +95 -0
  42. package/src/getThreadInfo.js +194 -0
  43. package/src/getThreadInfoDeprecated.js +77 -0
  44. package/src/getThreadList.js +219 -0
  45. package/src/getThreadListDeprecated.js +86 -0
  46. package/src/getThreadPictures.js +85 -0
  47. package/src/getUserID.js +67 -0
  48. package/src/getUserInfo.js +89 -0
  49. package/src/handleFriendRequest.js +56 -0
  50. package/src/handleMessageRequest.js +65 -0
  51. package/src/httpGet.js +53 -0
  52. package/src/httpPost.js +53 -0
  53. package/src/httpPostFormData.js +58 -0
  54. package/src/listenMqtt.js +683 -0
  55. package/src/listenNotification.js +96 -0
  56. package/src/logout.js +77 -0
  57. package/src/markAsDelivered.js +53 -0
  58. package/src/markAsRead.js +74 -0
  59. package/src/markAsReadAll.js +46 -0
  60. package/src/markAsSeen.js +57 -0
  61. package/src/muteThread.js +49 -0
  62. package/src/pinMessage.js +60 -0
  63. package/src/refreshFb_dtsg.js +75 -0
  64. package/src/removeUserFromGroup.js +59 -0
  65. package/src/resolvePhotoUrl.js +47 -0
  66. package/src/searchForThread.js +55 -0
  67. package/src/searchStickers.js +59 -0
  68. package/src/sendMessage.js +444 -0
  69. package/src/sendMessageMqtt.js +326 -0
  70. package/src/sendTypingIndicator.js +54 -0
  71. package/src/setMessageReaction.js +126 -0
  72. package/src/setMessageReactionMqtt.js +74 -0
  73. package/src/setPostReaction.js +103 -0
  74. package/src/setProfileGuard.js +66 -0
  75. package/src/setStoryReaction.js +97 -0
  76. package/src/setTitle.js +100 -0
  77. package/src/shareContact.js +101 -0
  78. package/src/shareLink.js +105 -0
  79. package/src/stopListenMqtt.js +47 -0
  80. package/src/threadColors.js +119 -0
  81. package/src/unfriend.js +58 -0
  82. package/src/unsendMessage.js +51 -0
  83. package/src/uploadAttachment.js +98 -0
  84. package/utils.js +919 -0
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ module.exports = (defaultFuncs, api, ctx) => {
4
+ return (str) => ctx?.globalOptions?.[str];
5
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ module.exports = (defaultFuncs, api, ctx) => {
4
+ return function getRegion() {
5
+ return ctx?.region;
6
+ };
7
+ };
@@ -0,0 +1,496 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+
5
+ // ফাইলের এক্সটেনশন বের করার হেল্পার ফাংশন
6
+ function getExtension(original_extension, filename = "") {
7
+ if (original_extension) {
8
+ return original_extension;
9
+ }
10
+ const extension = filename.split(".").pop();
11
+ return extension === filename ? "" : extension;
12
+ }
13
+
14
+ // গ্রাফকিউএল রেসপন্স থেকে বিভিন্ন মিডিয়া অ্যাটাচমেন্ট ফরম্যাট করার ফাংশন
15
+ function formatAttachmentsGraphQLResponse(attachment) {
16
+ switch (attachment.__typename) {
17
+ case "MessageImage":
18
+ return {
19
+ type: "photo",
20
+ ID: attachment.legacy_attachment_id,
21
+ filename: attachment.filename,
22
+ original_extension: getExtension(
23
+ attachment.original_extension,
24
+ attachment.filename
25
+ ),
26
+ thumbnailUrl: attachment.thumbnail.uri,
27
+ previewUrl: attachment.preview.uri,
28
+ previewWidth: attachment.preview.width,
29
+ previewHeight: attachment.preview.height,
30
+ largePreviewUrl: attachment.large_preview.uri,
31
+ largePreviewHeight: attachment.large_preview.height,
32
+ largePreviewWidth: attachment.large_preview.width,
33
+ url: attachment.large_preview.uri,
34
+ width: attachment.large_preview.width,
35
+ height: attachment.large_preview.height,
36
+ name: attachment.filename,
37
+ attributionApp: attachment.attribution_app
38
+ ? {
39
+ attributionAppID: attachment.attribution_app.id,
40
+ name: attachment.attribution_app.name,
41
+ logo: attachment.attribution_app.square_logo,
42
+ }
43
+ : null,
44
+ };
45
+ case "MessageAnimatedImage":
46
+ return {
47
+ type: "animated_image",
48
+ ID: attachment.legacy_attachment_id,
49
+ filename: attachment.filename,
50
+ original_extension: getExtension(
51
+ attachment.original_extension,
52
+ attachment.filename
53
+ ),
54
+ previewUrl: attachment.preview_image.uri,
55
+ previewWidth: attachment.preview_image.width,
56
+ previewHeight: attachment.preview_image.height,
57
+ url: attachment.animated_image.uri,
58
+ width: attachment.animated_image.width,
59
+ height: attachment.animated_image.height,
60
+ thumbnailUrl: attachment.preview_image.uri,
61
+ name: attachment.filename,
62
+ facebookUrl: attachment.animated_image.uri,
63
+ rawGifImage: attachment.animated_image.uri,
64
+ animatedGifUrl: attachment.animated_image.uri,
65
+ animatedGifPreviewUrl: attachment.preview_image.uri,
66
+ animatedWebpUrl: attachment.animated_image.uri,
67
+ animatedWebpPreviewUrl: attachment.preview_image.uri,
68
+ attributionApp: attachment.attribution_app
69
+ ? {
70
+ attributionAppID: attachment.attribution_app.id,
71
+ name: attachment.attribution_app.name,
72
+ logo: attachment.attribution_app.square_logo,
73
+ }
74
+ : null,
75
+ };
76
+ case "MessageVideo":
77
+ return {
78
+ type: "video",
79
+ ID: attachment.legacy_attachment_id,
80
+ filename: attachment.filename,
81
+ original_extension: getExtension(
82
+ attachment.original_extension,
83
+ attachment.filename
84
+ ),
85
+ duration: attachment.playable_duration_in_ms,
86
+ thumbnailUrl: attachment.large_image.uri,
87
+ previewUrl: attachment.large_image.uri,
88
+ previewWidth: attachment.large_image.width,
89
+ previewHeight: attachment.large_image.height,
90
+ url: attachment.playable_url,
91
+ width: attachment.original_dimensions.x,
92
+ height: attachment.original_dimensions.y,
93
+ videoType: attachment.video_type?.toLowerCase(),
94
+ };
95
+ case "MessageFile":
96
+ return {
97
+ type: "file",
98
+ ID: attachment.message_file_fbid,
99
+ filename: attachment.filename,
100
+ original_extension: getExtension(
101
+ attachment.original_extension,
102
+ attachment.filename
103
+ ),
104
+ url: attachment.url,
105
+ isMalicious: attachment.is_malicious,
106
+ contentType: attachment.content_type,
107
+ name: attachment.filename,
108
+ mimeType: "",
109
+ fileSize: -1,
110
+ };
111
+ case "MessageAudio":
112
+ return {
113
+ type: "audio",
114
+ ID: attachment.url_shimhash,
115
+ filename: attachment.filename,
116
+ original_extension: getExtension(
117
+ attachment.original_extension,
118
+ attachment.filename
119
+ ),
120
+ duration: attachment.playable_duration_in_ms,
121
+ audioType: attachment.audio_type,
122
+ url: attachment.playable_url,
123
+ isVoiceMail: attachment.is_voicemail,
124
+ };
125
+ default:
126
+ return {
127
+ error: `Don't know about attachment type ${attachment.__typename}`,
128
+ };
129
+ }
130
+ }
131
+
132
+ // এক্সটেনসিবল শেয়ার কন্টেন্ট ফরম্যাট করার ফাংশন
133
+ function formatExtensibleAttachment(attachment) {
134
+ if (attachment.story_attachment) {
135
+ const { story_attachment } = attachment;
136
+ const media = story_attachment.media;
137
+ const hasMedia = media != null && (media.animated_image != null || media.image != null);
138
+ const mediaUri = hasMedia ? (media.animated_image || media.image).uri : null;
139
+ const mediaWidth = hasMedia ? (media.animated_image || media.image).width : null;
140
+ const mediaHeight = hasMedia ? (media.animated_image || media.image).height : null;
141
+
142
+ return {
143
+ type: "share",
144
+ ID: attachment.legacy_attachment_id,
145
+ url: story_attachment.url,
146
+ title: story_attachment.title_with_entities?.text,
147
+ description: story_attachment.description?.text,
148
+ source: story_attachment.source?.text,
149
+ image: mediaUri,
150
+ width: mediaWidth,
151
+ height: mediaHeight,
152
+ playable: media?.is_playable,
153
+ duration: media?.playable_duration_in_ms,
154
+ playableUrl: media?.playable_url,
155
+ subattachments: story_attachment.subattachments,
156
+ properties: (story_attachment.properties || []).reduce((obj, cur) => {
157
+ obj[cur.key] = cur.value?.text;
158
+ return obj;
159
+ }, {}),
160
+ animatedImageSize: "",
161
+ facebookUrl: "",
162
+ styleList: "",
163
+ target: "",
164
+ thumbnailUrl: mediaUri,
165
+ thumbnailWidth: mediaWidth,
166
+ thumbnailHeight: mediaHeight,
167
+ };
168
+ }
169
+ return { error: "Don't know what to do with extensible_attachment." };
170
+ }
171
+
172
+ function formatReactionsGraphQL(reaction) {
173
+ return {
174
+ reaction: reaction.reaction,
175
+ userID: reaction.user?.id,
176
+ };
177
+ }
178
+
179
+ // অ্যাডমিন ইভেন্ট ডাটা ম্যাপিং
180
+ function formatEventData(event) {
181
+ if (event == null) {
182
+ return {};
183
+ }
184
+
185
+ switch (event.__typename) {
186
+ case "ThemeColorExtensibleMessageAdminText":
187
+ return { color: event.theme_color };
188
+ case "ThreadNicknameExtensibleMessageAdminText":
189
+ return {
190
+ nickname: event.nickname,
191
+ participantID: event.participant_id,
192
+ };
193
+ case "ThreadIconExtensibleMessageAdminText":
194
+ return { threadIcon: event.thread_icon };
195
+ case "InstantGameUpdateExtensibleMessageAdminText":
196
+ return {
197
+ gameID: event.game?.id,
198
+ update_type: event.update_type,
199
+ collapsed_text: event.collapsed_text,
200
+ expanded_text: event.expanded_text,
201
+ instant_game_update_data: event.instant_game_update_data,
202
+ };
203
+ case "GameScoreExtensibleMessageAdminText":
204
+ return { game_type: event.game_type };
205
+ case "RtcCallLogExtensibleMessageAdminText":
206
+ return {
207
+ event: event.event,
208
+ is_video_call: event.is_video_call,
209
+ server_info_data: event.server_info_data,
210
+ };
211
+ case "GroupPollExtensibleMessageAdminText":
212
+ return {
213
+ event_type: event.event_type,
214
+ total_count: event.total_count,
215
+ question: event.question,
216
+ };
217
+ case "AcceptPendingThreadExtensibleMessageAdminText":
218
+ return {
219
+ accepter_id: event.accepter_id,
220
+ requester_id: event.requester_id,
221
+ };
222
+ case "ConfirmFriendRequestExtensibleMessageAdminText":
223
+ return {
224
+ friend_request_recipient: event.friend_request_recipient,
225
+ friend_request_sender: event.friend_request_sender,
226
+ };
227
+ case "AddContactExtensibleMessageAdminText":
228
+ return {
229
+ contact_added_id: event.contact_added_id,
230
+ contact_adder_id: event.contact_adder_id,
231
+ };
232
+ case "AdExtensibleMessageAdminText":
233
+ return {
234
+ ad_client_token: event.ad_client_token,
235
+ ad_id: event.ad_id,
236
+ ad_preferences_link: event.ad_preferences_link,
237
+ ad_properties: event.ad_properties,
238
+ };
239
+ case "ParticipantJoinedGroupCallExtensibleMessageAdminText":
240
+ case "ThreadEphemeralTtlModeExtensibleMessageAdminText":
241
+ case "StartedSharingVideoExtensibleMessageAdminText":
242
+ case "LightweightEventCreateExtensibleMessageAdminText":
243
+ case "LightweightEventNotifyExtensibleMessageAdminText":
244
+ case "LightweightEventNotifyBeforeEventExtensibleMessageAdminText":
245
+ case "LightweightEventUpdateTitleExtensibleMessageAdminText":
246
+ case "LightweightEventUpdateTimeExtensibleMessageAdminText":
247
+ case "LightweightEventUpdateLocationExtensibleMessageAdminText":
248
+ case "LightweightEventDeleteExtensibleMessageAdminText":
249
+ return {};
250
+ default:
251
+ return {
252
+ error: `Don't know what to with event data type ${event.__typename}`,
253
+ };
254
+ }
255
+ }
256
+
257
+ // সম্পূর্ণ চ্যাট হিস্ট্রি পার্স করার মেইন হেল্পার
258
+ function formatMessagesGraphQLResponse(data) {
259
+ const messageThread = data.o0.data.message_thread;
260
+ const threadID = messageThread.thread_key.thread_fbid
261
+ ? messageThread.thread_key.thread_fbid
262
+ : messageThread.thread_key.other_user_id;
263
+
264
+ return messageThread.messages.nodes.map(d => {
265
+ switch (d.__typename) {
266
+ case "UserMessage":
267
+ let maybeStickerAttachment = null;
268
+ if (d.sticker) {
269
+ maybeStickerAttachment = [
270
+ {
271
+ type: "sticker",
272
+ ID: d.sticker.id,
273
+ url: d.sticker.url,
274
+ packID: d.sticker.pack?.id,
275
+ spriteUrl: d.sticker.sprite_image,
276
+ spriteUrl2x: d.sticker.sprite_image_2x,
277
+ width: d.sticker.width,
278
+ height: d.sticker.height,
279
+ caption: d.snippet,
280
+ description: d.sticker.label,
281
+ frameCount: d.sticker.frame_count,
282
+ frameRate: d.sticker.frame_rate,
283
+ framesPerRow: d.sticker.frames_per_row,
284
+ framesPerCol: d.sticker.frames_per_col,
285
+ stickerID: d.sticker.id,
286
+ spriteURI: d.sticker.sprite_image,
287
+ spriteURI2x: d.sticker.sprite_image_2x,
288
+ },
289
+ ];
290
+ }
291
+
292
+ const mentionsObj = {};
293
+ if (d.message !== null) {
294
+ d.message.ranges.forEach(e => {
295
+ mentionsObj[e.entity.id] = d.message.text.substr(e.offset, e.length);
296
+ });
297
+ }
298
+
299
+ return {
300
+ type: "message",
301
+ attachments: maybeStickerAttachment
302
+ ? maybeStickerAttachment
303
+ : d.blob_attachments && d.blob_attachments.length > 0
304
+ ? d.blob_attachments.map(formatAttachmentsGraphQLResponse)
305
+ : d.extensible_attachment
306
+ ? [formatExtensibleAttachment(d.extensible_attachment)]
307
+ : [],
308
+ body: d.message !== null ? d.message.text : "",
309
+ isGroup: messageThread.thread_type === "GROUP",
310
+ messageID: d.message_id,
311
+ senderID: d.message_sender.id,
312
+ threadID: threadID,
313
+ timestamp: d.timestamp_precise,
314
+ mentions: mentionsObj,
315
+ isUnread: d.unread,
316
+ messageReactions: d.message_reactions
317
+ ? d.message_reactions.map(formatReactionsGraphQL)
318
+ : null,
319
+ isSponsored: d.is_sponsored,
320
+ snippet: d.snippet,
321
+ };
322
+ case "ThreadNameMessage":
323
+ return {
324
+ type: "event",
325
+ messageID: d.message_id,
326
+ threadID: threadID,
327
+ isGroup: messageThread.thread_type === "GROUP",
328
+ senderID: d.message_sender.id,
329
+ timestamp: d.timestamp_precise,
330
+ eventType: "change_thread_name",
331
+ snippet: d.snippet,
332
+ eventData: { threadName: d.thread_name },
333
+ author: d.message_sender.id,
334
+ logMessageType: "log:thread-name",
335
+ logMessageData: { name: d.thread_name },
336
+ };
337
+ case "ThreadImageMessage":
338
+ return {
339
+ type: "event",
340
+ messageID: d.message_id,
341
+ threadID: threadID,
342
+ isGroup: messageThread.thread_type === "GROUP",
343
+ senderID: d.message_sender.id,
344
+ timestamp: d.timestamp_precise,
345
+ eventType: "change_thread_image",
346
+ snippet: d.snippet,
347
+ eventData:
348
+ d.image_with_metadata == null
349
+ ? {}
350
+ : {
351
+ threadImage: {
352
+ attachmentID: d.image_with_metadata.legacy_attachment_id,
353
+ width: d.image_with_metadata.original_dimensions.x,
354
+ height: d.image_with_metadata.original_dimensions.y,
355
+ url: d.image_with_metadata.preview.uri,
356
+ },
357
+ },
358
+ logMessageType: "log:thread-icon",
359
+ logMessageData: {
360
+ thread_icon: d.image_with_metadata ? d.image_with_metadata.preview.uri : null,
361
+ },
362
+ };
363
+ case "ParticipantLeftMessage":
364
+ return {
365
+ type: "event",
366
+ messageID: d.message_id,
367
+ threadID: threadID,
368
+ isGroup: messageThread.thread_type === "GROUP",
369
+ senderID: d.message_sender.id,
370
+ timestamp: d.timestamp_precise,
371
+ eventType: "remove_participants",
372
+ snippet: d.snippet,
373
+ eventData: {
374
+ participantsRemoved: d.participants_removed.map(p => p.id),
375
+ },
376
+ logMessageType: "log:unsubscribe",
377
+ logMessageData: {
378
+ leftParticipantFbId: d.participants_removed.map(p => p.id),
379
+ },
380
+ };
381
+ case "ParticipantsAddedMessage":
382
+ return {
383
+ type: "event",
384
+ messageID: d.message_id,
385
+ threadID: threadID,
386
+ isGroup: messageThread.thread_type === "GROUP",
387
+ senderID: d.message_sender.id,
388
+ timestamp: d.timestamp_precise,
389
+ eventType: "add_participants",
390
+ snippet: d.snippet,
391
+ eventData: {
392
+ participantsAdded: d.participants_added.map(p => p.id),
393
+ },
394
+ logMessageType: "log:subscribe",
395
+ logMessageData: {
396
+ addedParticipants: d.participants_added.map(p => p.id),
397
+ },
398
+ };
399
+ case "VideoCallMessage":
400
+ return {
401
+ type: "event",
402
+ messageID: d.message_id,
403
+ threadID: threadID,
404
+ isGroup: messageThread.thread_type === "GROUP",
405
+ senderID: d.message_sender.id,
406
+ timestamp: d.timestamp_precise,
407
+ eventType: "video_call",
408
+ snippet: d.snippet,
409
+ logMessageType: "other",
410
+ };
411
+ case "VoiceCallMessage":
412
+ return {
413
+ type: "event",
414
+ messageID: d.message_id,
415
+ threadID: threadID,
416
+ isGroup: messageThread.thread_type === "GROUP",
417
+ senderID: d.message_sender.id,
418
+ timestamp: d.timestamp_precise,
419
+ eventType: "voice_call",
420
+ snippet: d.snippet,
421
+ logMessageType: "other",
422
+ };
423
+ case "GenericAdminTextMessage":
424
+ return {
425
+ type: "event",
426
+ messageID: d.message_id,
427
+ threadID: threadID,
428
+ isGroup: messageThread.thread_type === "GROUP",
429
+ senderID: d.message_sender.id,
430
+ timestamp: d.timestamp_precise,
431
+ snippet: d.snippet,
432
+ eventType: d.extensible_message_admin_text_type.toLowerCase(),
433
+ eventData: formatEventData(d.extensible_message_admin_text),
434
+ logMessageType: utils.getAdminTextMessageType(
435
+ d.extensible_message_admin_text_type
436
+ ),
437
+ logMessageData: d.extensible_message_admin_text,
438
+ };
439
+ default:
440
+ return { error: `Don't know about message type ${d.__typename}` };
441
+ }
442
+ });
443
+ }
444
+
445
+ module.exports = function (defaultFuncs, api, ctx) {
446
+ return function getThreadHistoryGraphQL(threadID, amount, timestamp, callback) {
447
+ let resolveFunc = () => {};
448
+ let rejectFunc = () => {};
449
+ const returnPromise = new Promise((resolve, reject) => {
450
+ resolveFunc = resolve;
451
+ rejectFunc = reject;
452
+ });
453
+
454
+ if (!callback) {
455
+ callback = (err, data) => {
456
+ if (err) return rejectFunc(err);
457
+ resolveFunc(data);
458
+ };
459
+ }
460
+
461
+ const form = {
462
+ av: ctx.globalOptions.pageID,
463
+ queries: JSON.stringify({
464
+ o0: {
465
+ doc_id: "1498317363570230",
466
+ query_params: {
467
+ id: threadID,
468
+ message_limit: amount,
469
+ load_messages: 1,
470
+ load_read_receipts: false,
471
+ before: timestamp,
472
+ },
473
+ },
474
+ }),
475
+ };
476
+
477
+ defaultFuncs
478
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
479
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
480
+ .then(resData => {
481
+ if (resData.error) {
482
+ throw resData;
483
+ }
484
+ if (resData[resData.length - 1].error_results !== 0) {
485
+ throw new Error("There was an error_result in GraphQLBatch.");
486
+ }
487
+ return callback(null, formatMessagesGraphQLResponse(resData[0]));
488
+ })
489
+ .catch(err => {
490
+ utils.error("getThreadHistoryGraphQL", err);
491
+ return callback(err);
492
+ });
493
+
494
+ return returnPromise;
495
+ };
496
+ };
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+
5
+ module.exports = function (defaultFuncs, api, ctx) {
6
+ return function getThreadHistory(threadID, amount, timestamp, callback) {
7
+ let resolveFunc = () => {};
8
+ let rejectFunc = () => {};
9
+
10
+ const returnPromise = new Promise((resolve, reject) => {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ // কলব্যাক না থাকলে প্রমিজ হ্যান্ডলার সেট করা হচ্ছে
16
+ if (!callback) {
17
+ callback = (err, friendList) => {
18
+ if (err) {
19
+ return rejectFunc(err);
20
+ }
21
+ resolveFunc(friendList);
22
+ };
23
+ }
24
+
25
+ const form = {
26
+ client: "mercury"
27
+ };
28
+
29
+ // ইউজার নাকি পেজ/গ্রুপ থ্রেড তা যাচাই করার জন্য ইউজার ইনফো ফেচ করা হচ্ছে
30
+ api.getUserInfo(threadID, (err, res) => {
31
+ if (err) {
32
+ return callback(err);
33
+ }
34
+
35
+ const key = Object.keys(res).length > 0 ? "user_ids" : "thread_fbids";
36
+ form[`messages[${key}][${threadID}][offset]`] = 0;
37
+ form[`messages[${key}][${threadID}][timestamp]`] = timestamp;
38
+ form[`messages[${key}][${threadID}][limit]`] = amount;
39
+
40
+ if (ctx.globalOptions.pageID) {
41
+ form.request_user_id = ctx.globalOptions.pageID;
42
+ }
43
+
44
+ defaultFuncs
45
+ .post(
46
+ "https://www.facebook.com/ajax/mercury/thread_info.php",
47
+ ctx.jar,
48
+ form
49
+ )
50
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
51
+ .then(resData => {
52
+ if (resData.error) {
53
+ throw resData;
54
+ } else if (!resData.payload) {
55
+ throw { error: "Could not retrieve thread history." };
56
+ }
57
+
58
+ // কোনো মেসেজ হিস্ট্রি না থাকলে খালি অ্যারে দিয়ে ক্র্যাশ আটকানো হচ্ছে
59
+ if (!resData.payload.actions) {
60
+ resData.payload.actions = [];
61
+ }
62
+
63
+ const userIDs = {};
64
+ resData.payload.actions.forEach(v => {
65
+ userIDs[v.author.split(":").pop()] = "";
66
+ });
67
+
68
+ // মেসেজদাতাদের নাম বের করার জন্য সবার ইউজার ইনফো ফেচ করা হচ্ছে
69
+ api.getUserInfo(Object.keys(userIDs), (err, data) => {
70
+ if (err) return callback(err);
71
+
72
+ resData.payload.actions.forEach(v => {
73
+ const senderID = v.author.split(":").pop();
74
+ const sender = data[senderID];
75
+
76
+ v.sender_name = sender ? sender.name : "Facebook User";
77
+ v.sender_fbid = v.author;
78
+ delete v.author;
79
+ });
80
+
81
+ callback(
82
+ null,
83
+ resData.payload.actions.map(utils.formatHistoryMessage)
84
+ );
85
+ });
86
+ })
87
+ .catch(err => {
88
+ utils.error("getThreadHistory", err);
89
+ return callback(err);
90
+ });
91
+ });
92
+
93
+ return returnPromise;
94
+ };
95
+ };