fca-arif-babu 1.0.21

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 (87) hide show
  1. package/.github/workflows/publish.yml +20 -0
  2. package/LICENSE-MIT +21 -0
  3. package/README.md +20 -0
  4. package/index.js +489 -0
  5. package/package.json +47 -0
  6. package/replit.nix +3 -0
  7. package/src/addExternalModule.js +25 -0
  8. package/src/addUserToGroup.js +115 -0
  9. package/src/changeAdminStatus.js +103 -0
  10. package/src/changeArchivedStatus.js +55 -0
  11. package/src/changeAvatar.js +136 -0
  12. package/src/changeAvatarV2.js +86 -0
  13. package/src/changeBio.js +76 -0
  14. package/src/changeBlockedStatus.js +49 -0
  15. package/src/changeBlockedStatusMqtt.js +80 -0
  16. package/src/changeCover.js +72 -0
  17. package/src/changeGroupImage.js +135 -0
  18. package/src/changeName.js +78 -0
  19. package/src/changeNickname.js +59 -0
  20. package/src/changeThreadColor.js +65 -0
  21. package/src/changeThreadEmoji.js +55 -0
  22. package/src/changeUsername.js +58 -0
  23. package/src/createCommentPost.js +229 -0
  24. package/src/createNewGroup.js +88 -0
  25. package/src/createPoll.js +71 -0
  26. package/src/createPost.js +275 -0
  27. package/src/data/getThreadInfo.json +1 -0
  28. package/src/deleteMessage.js +56 -0
  29. package/src/deleteThread.js +56 -0
  30. package/src/editMessage.js +59 -0
  31. package/src/editMessageOld.js +67 -0
  32. package/src/follow.js +74 -0
  33. package/src/forwardAttachment.js +60 -0
  34. package/src/getAccess.js +112 -0
  35. package/src/getAvatarUser.js +78 -0
  36. package/src/getBotInitialData.js +42 -0
  37. package/src/getCurrentUserID.js +7 -0
  38. package/src/getEmojiUrl.js +29 -0
  39. package/src/getFriendsList.js +83 -0
  40. package/src/getMessage.js +835 -0
  41. package/src/getRegion.js +7 -0
  42. package/src/getThreadHistory.js +680 -0
  43. package/src/getThreadHistoryDeprecated.js +93 -0
  44. package/src/getThreadInfo.js +227 -0
  45. package/src/getThreadInfoDeprecated.js +80 -0
  46. package/src/getThreadList.js +270 -0
  47. package/src/getThreadListDeprecated.js +75 -0
  48. package/src/getThreadPictures.js +79 -0
  49. package/src/getUID.js +122 -0
  50. package/src/getUserID.js +66 -0
  51. package/src/getUserInfo.js +71 -0
  52. package/src/handleFriendRequest.js +57 -0
  53. package/src/handleMessageRequest.js +65 -0
  54. package/src/httpGet.js +64 -0
  55. package/src/httpPost.js +64 -0
  56. package/src/httpPostFormData.js +70 -0
  57. package/src/listenMqtt.js +703 -0
  58. package/src/listenNotification.js +85 -0
  59. package/src/logout.js +75 -0
  60. package/src/markAsDelivered.js +55 -0
  61. package/src/markAsRead.js +85 -0
  62. package/src/markAsReadAll.js +50 -0
  63. package/src/markAsSeen.js +61 -0
  64. package/src/muteThread.js +52 -0
  65. package/src/pinMessage.js +59 -0
  66. package/src/refreshFb_dtsg.js +89 -0
  67. package/src/removeUserFromGroup.js +79 -0
  68. package/src/resolvePhotoUrl.js +45 -0
  69. package/src/searchForThread.js +53 -0
  70. package/src/searchStickers.js +53 -0
  71. package/src/sendMessage.js +442 -0
  72. package/src/sendMessageMqtt.js +316 -0
  73. package/src/sendTypingIndicator.js +28 -0
  74. package/src/setMessageReaction.js +122 -0
  75. package/src/setMessageReactionMqtt.js +62 -0
  76. package/src/setPostReaction.js +112 -0
  77. package/src/setProfileGuard.js +44 -0
  78. package/src/setStoryReaction.js +64 -0
  79. package/src/setTitle.js +90 -0
  80. package/src/shareContact.js +110 -0
  81. package/src/shareLink.js +59 -0
  82. package/src/stopListenMqtt.js +23 -0
  83. package/src/threadColors.js +131 -0
  84. package/src/unfriend.js +52 -0
  85. package/src/unsendMessage.js +45 -0
  86. package/src/uploadAttachment.js +94 -0
  87. package/utils.js +1416 -0
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ // @NethWs3Dev
5
+
6
+ module.exports = function(defaultFuncs, api, ctx) {
7
+ return function getThreadHistory(threadID, amount, timestamp, callback) {
8
+ var resolveFunc = function(){};
9
+ var rejectFunc = function(){};
10
+ var returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ callback = function (err, friendList) {
17
+ if (err) {
18
+ return rejectFunc(err);
19
+ }
20
+ resolveFunc(friendList);
21
+ };
22
+ }
23
+
24
+ if (!callback) {
25
+ throw { error: "getThreadHistory: need callback" };
26
+ }
27
+
28
+ var form = {
29
+ client: "mercury"
30
+ };
31
+
32
+ api.getUserInfo(threadID, function(err, res) {
33
+ if (err) {
34
+ return callback(err);
35
+ }
36
+ var key = Object.keys(res).length > 0 ? "user_ids" : "thread_fbids";
37
+ form["messages[" + key + "][" + threadID + "][offset]"] = 0;
38
+ form["messages[" + key + "][" + threadID + "][timestamp]"] = timestamp;
39
+ form["messages[" + key + "][" + threadID + "][limit]"] = amount;
40
+
41
+ if (ctx.globalOptions.pageID)
42
+ form.request_user_id = ctx.globalOptions.pageID;
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(function(resData) {
52
+ if (resData.error) {
53
+ throw resData;
54
+ } else if (!resData.payload) {
55
+ throw { error: "Could not retrieve thread history." };
56
+ }
57
+
58
+ // Asking for message history from a thread with no message history
59
+ // will return undefined for actions here
60
+ if (!resData.payload.actions) {
61
+ resData.payload.actions = [];
62
+ }
63
+
64
+ var userIDs = {};
65
+ resData.payload.actions.forEach(function(v) {
66
+ userIDs[v.author.split(":").pop()] = "";
67
+ });
68
+
69
+ api.getUserInfo(Object.keys(userIDs), function(err, data) {
70
+ if (err) return callback(err); //callback({error: "Could not retrieve user information in getThreadHistory."});
71
+
72
+ resData.payload.actions.forEach(function(v) {
73
+ var sender = data[v.author.split(":").pop()];
74
+ if (sender) v.sender_name = sender.name;
75
+ else v.sender_name = "Facebook User";
76
+ v.sender_fbid = v.author;
77
+ delete v.author;
78
+ });
79
+
80
+ callback(
81
+ null,
82
+ resData.payload.actions.map(utils.formatHistoryMessage)
83
+ );
84
+ });
85
+ })
86
+ .catch(function(err) {
87
+ console.error("getThreadHistory", err);
88
+ return callback(err);
89
+ });
90
+ });
91
+ return returnPromise;
92
+ };
93
+ };
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ // @NethWs3Dev
5
+
6
+ function formatEventReminders(reminder) {
7
+ return {
8
+ reminderID: reminder.id,
9
+ eventCreatorID: reminder.lightweight_event_creator.id,
10
+ time: reminder.time,
11
+ eventType: reminder.lightweight_event_type.toLowerCase(),
12
+ locationName: reminder.location_name,
13
+ locationCoordinates: reminder.location_coordinates,
14
+ locationPage: reminder.location_page,
15
+ eventStatus: reminder.lightweight_event_status.toLowerCase(),
16
+ note: reminder.note,
17
+ repeatMode: reminder.repeat_mode.toLowerCase(),
18
+ eventTitle: reminder.event_title,
19
+ triggerMessage: reminder.trigger_message,
20
+ secondsToNotifyBefore: reminder.seconds_to_notify_before,
21
+ allowsRsvp: reminder.allows_rsvp,
22
+ relatedEvent: reminder.related_event,
23
+ members: reminder.event_reminder_members.edges.map(function (member) {
24
+ return {
25
+ memberID: member.node.id,
26
+ state: member.guest_list_state.toLowerCase(),
27
+ };
28
+ }),
29
+ };
30
+ }
31
+
32
+ function formatThreadGraphQLResponse(data) {
33
+ if (data.errors) return null; // Return null if there are errors
34
+ const messageThread = data.message_thread;
35
+ if (!messageThread) return null;
36
+
37
+ const threadID = messageThread.thread_key.thread_fbid
38
+ ? messageThread.thread_key.thread_fbid
39
+ : messageThread.thread_key.other_user_id;
40
+
41
+ const lastM = messageThread.last_message;
42
+ const snippetID =
43
+ lastM &&
44
+ lastM.nodes &&
45
+ lastM.nodes[0] &&
46
+ lastM.nodes[0].message_sender &&
47
+ lastM.nodes[0].message_sender.messaging_actor
48
+ ? lastM.nodes[0].message_sender.messaging_actor.id
49
+ : null;
50
+ const snippetText =
51
+ lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
52
+ const lastR = messageThread.last_read_receipt;
53
+ const lastReadTimestamp =
54
+ lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
55
+ ? lastR.nodes[0].timestamp_precise
56
+ : null;
57
+
58
+ return {
59
+ threadID: threadID,
60
+ threadName: messageThread.name,
61
+ participantIDs: messageThread.all_participants.edges.map(
62
+ (d) => d.node.messaging_actor.id,
63
+ ),
64
+ userInfo: messageThread.all_participants.edges.map((d) => ({
65
+ id: d.node.messaging_actor.id,
66
+ name: d.node.messaging_actor.name,
67
+ firstName: d.node.messaging_actor.short_name,
68
+ vanity: d.node.messaging_actor.username,
69
+ url: d.node.messaging_actor.url,
70
+ thumbSrc: d.node.messaging_actor.big_image_src.uri,
71
+ profileUrl: d.node.messaging_actor.big_image_src.uri,
72
+ gender: d.node.messaging_actor.gender,
73
+ type: d.node.messaging_actor.__typename,
74
+ isFriend: d.node.messaging_actor.is_viewer_friend,
75
+ isBirthday: !!d.node.messaging_actor.is_birthday,
76
+ })),
77
+ unreadCount: messageThread.unread_count,
78
+ messageCount: messageThread.messages_count,
79
+ timestamp: messageThread.updated_time_precise,
80
+ muteUntil: messageThread.mute_until,
81
+ isGroup: messageThread.thread_type == "GROUP",
82
+ isSubscribed: messageThread.is_viewer_subscribed,
83
+ isArchived: messageThread.has_viewer_archived,
84
+ folder: messageThread.folder,
85
+ cannotReplyReason: messageThread.cannot_reply_reason,
86
+ eventReminders: messageThread.event_reminders
87
+ ? messageThread.event_reminders.nodes.map(formatEventReminders)
88
+ : null,
89
+ emoji: messageThread.customization_info
90
+ ? messageThread.customization_info.emoji
91
+ : null,
92
+ color:
93
+ messageThread.customization_info &&
94
+ messageThread.customization_info.outgoing_bubble_color
95
+ ? messageThread.customization_info.outgoing_bubble_color.slice(2)
96
+ : null,
97
+ threadTheme: messageThread.thread_theme,
98
+ nicknames:
99
+ messageThread.customization_info &&
100
+ messageThread.customization_info.participant_customizations
101
+ ? messageThread.customization_info.participant_customizations.reduce(
102
+ function (res, val) {
103
+ if (val.nickname) res[val.participant_id] = val.nickname;
104
+ return res;
105
+ },
106
+ {},
107
+ )
108
+ : {},
109
+ adminIDs: messageThread.thread_admins,
110
+ approvalMode: Boolean(messageThread.approval_mode),
111
+ approvalQueue: messageThread.group_approval_queue.nodes.map((a) => ({
112
+ inviterID: a.inviter.id,
113
+ requesterID: a.requester.id,
114
+ timestamp: a.request_timestamp,
115
+ request_source: a.request_source,
116
+ })),
117
+ reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
118
+ mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
119
+ isPinProtected: messageThread.is_pin_protected,
120
+ relatedPageThread: messageThread.related_page_thread,
121
+ name: messageThread.name,
122
+ snippet: snippetText,
123
+ snippetSender: snippetID,
124
+ snippetAttachments: [],
125
+ serverTimestamp: messageThread.updated_time_precise,
126
+ imageSrc: messageThread.image ? messageThread.image.uri : null,
127
+ isCanonicalUser: messageThread.is_canonical_neo_user,
128
+ isCanonical: messageThread.thread_type != "GROUP",
129
+ recipientsLoadable: true,
130
+ hasEmailParticipant: false,
131
+ readOnly: false,
132
+ canReply: messageThread.cannot_reply_reason == null,
133
+ lastMessageTimestamp: messageThread.last_message
134
+ ? messageThread.last_message.timestamp_precise
135
+ : null,
136
+ lastMessageType: "message",
137
+ lastReadTimestamp: lastReadTimestamp,
138
+ threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
139
+ inviteLink: {
140
+ enable: messageThread.joinable_mode
141
+ ? messageThread.joinable_mode.mode == 1
142
+ : false,
143
+ link: messageThread.joinable_mode
144
+ ? messageThread.joinable_mode.link
145
+ : null,
146
+ },
147
+ };
148
+ }
149
+
150
+ module.exports = function (defaultFuncs, api, ctx) {
151
+ return function getThreadInfoGraphQL(threadID, callback) {
152
+ let resolveFunc = function () {};
153
+ let rejectFunc = function () {};
154
+ const returnPromise = new Promise(function (resolve, reject) {
155
+ resolveFunc = resolve;
156
+ rejectFunc = reject;
157
+ });
158
+
159
+ if (
160
+ utils.getType(callback) != "Function" &&
161
+ utils.getType(callback) != "AsyncFunction"
162
+ ) {
163
+ callback = function (err, data) {
164
+ if (err) {
165
+ return rejectFunc(err);
166
+ }
167
+ resolveFunc(data);
168
+ };
169
+ }
170
+
171
+ if (utils.getType(threadID) !== "Array") {
172
+ threadID = [threadID];
173
+ }
174
+
175
+ let form = {};
176
+ threadID.map(function (t, i) {
177
+ form["o" + i] = {
178
+ doc_id: "3449967031715030",
179
+ query_params: {
180
+ id: t,
181
+ message_limit: 0,
182
+ load_messages: false,
183
+ load_read_receipts: false,
184
+ before: null,
185
+ },
186
+ };
187
+ });
188
+
189
+ form = {
190
+ queries: JSON.stringify(form),
191
+ batch_name: "MessengerGraphQLThreadFetcher",
192
+ };
193
+
194
+ defaultFuncs
195
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
196
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
197
+ .then(function (resData) {
198
+ if (resData.error) {
199
+ throw resData;
200
+ }
201
+
202
+ const threadInfos = {};
203
+ for (let i = resData.length - 2; i >= 0; i--) {
204
+ const threadInfo = formatThreadGraphQLResponse(
205
+ resData[i][Object.keys(resData[i])[0]].data,
206
+ );
207
+ if (threadInfo) { // Only add valid threadInfo
208
+ threadInfos[
209
+ threadInfo.threadID || threadID[threadID.length - 1 - i]
210
+ ] = threadInfo;
211
+ }
212
+ }
213
+
214
+ if (Object.values(threadInfos).length == 1) {
215
+ callback(null, Object.values(threadInfos)[0]);
216
+ } else {
217
+ callback(null, threadInfos);
218
+ }
219
+ })
220
+ .catch(function () {
221
+ // Do nothing on error
222
+ callback(null, null);
223
+ });
224
+
225
+ return returnPromise;
226
+ };
227
+ };
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ // @NethWs3Dev
5
+
6
+ module.exports = function(defaultFuncs, api, ctx) {
7
+ return function getThreadInfo(threadID, callback) {
8
+ var resolveFunc = function(){};
9
+ var rejectFunc = function(){};
10
+ var returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ callback = function (err, friendList) {
17
+ if (err) {
18
+ return rejectFunc(err);
19
+ }
20
+ resolveFunc(friendList);
21
+ };
22
+ }
23
+
24
+ var form = {
25
+ client: "mercury"
26
+ };
27
+
28
+ api.getUserInfo(threadID, function(err, userRes) {
29
+ if (err) {
30
+ return callback(err);
31
+ }
32
+ var key = Object.keys(userRes).length > 0 ? "user_ids" : "thread_fbids";
33
+ form["threads[" + key + "][0]"] = threadID;
34
+
35
+ if (ctx.globalOptions.pageId)
36
+ form.request_user_id = ctx.globalOptions.pageId;
37
+
38
+ defaultFuncs
39
+ .post(
40
+ "https://www.facebook.com/ajax/mercury/thread_info.php",
41
+ ctx.jar,
42
+ form
43
+ )
44
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
45
+ .then(function(resData) {
46
+ if (resData.error) {
47
+ throw resData;
48
+ } else if (!resData.payload) {
49
+ throw {
50
+ error: "Could not retrieve thread Info."
51
+ };
52
+ }
53
+ var threadData = resData.payload.threads[0];
54
+ var userData = userRes[threadID];
55
+
56
+ if (threadData == null) {
57
+ throw {
58
+ error: "ThreadData is null"
59
+ };
60
+ }
61
+
62
+ threadData.name =
63
+ userData != null && userData.name != null
64
+ ? userData.name
65
+ : threadData.name;
66
+ threadData.image_src =
67
+ userData != null && userData.thumbSrc != null
68
+ ? userData.thumbSrc
69
+ : threadData.image_src;
70
+
71
+ callback(null, utils.formatThread(threadData));
72
+ })
73
+ .catch(function(err) {
74
+ console.error("getThreadInfo", err);
75
+ return callback(err);
76
+ });
77
+ });
78
+ return returnPromise;
79
+ };
80
+ };
@@ -0,0 +1,270 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ // @NethWs3Dev
5
+
6
+ function formatEventReminders(reminder) {
7
+ return {
8
+ reminderID: reminder.id,
9
+ eventCreatorID: reminder.lightweight_event_creator.id,
10
+ time: reminder.time,
11
+ eventType: reminder.lightweight_event_type.toLowerCase(),
12
+ locationName: reminder.location_name,
13
+ // @TODO verify this
14
+ locationCoordinates: reminder.location_coordinates,
15
+ locationPage: reminder.location_page,
16
+ eventStatus: reminder.lightweight_event_status.toLowerCase(),
17
+ note: reminder.note,
18
+ repeatMode: reminder.repeat_mode.toLowerCase(),
19
+ eventTitle: reminder.event_title,
20
+ triggerMessage: reminder.trigger_message,
21
+ secondsToNotifyBefore: reminder.seconds_to_notify_before,
22
+ allowsRsvp: reminder.allows_rsvp,
23
+ relatedEvent: reminder.related_event,
24
+ members: reminder.event_reminder_members.edges.map(function (member) {
25
+ return {
26
+ memberID: member.node.id,
27
+ state: member.guest_list_state.toLowerCase(),
28
+ };
29
+ }),
30
+ };
31
+ }
32
+
33
+ function formatThreadGraphQLResponse(messageThread) {
34
+ const threadID = messageThread.thread_key.thread_fbid
35
+ ? messageThread.thread_key.thread_fbid
36
+ : messageThread.thread_key.other_user_id;
37
+
38
+ // Remove me
39
+ const lastM = messageThread.last_message;
40
+ const snippetID =
41
+ lastM &&
42
+ lastM.nodes &&
43
+ lastM.nodes[0] &&
44
+ lastM.nodes[0].message_sender &&
45
+ lastM.nodes[0].message_sender.messaging_actor
46
+ ? lastM.nodes[0].message_sender.messaging_actor.id
47
+ : null;
48
+ const snippetText =
49
+ lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
50
+ const lastR = messageThread.last_read_receipt;
51
+ const lastReadTimestamp =
52
+ lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
53
+ ? lastR.nodes[0].timestamp_precise
54
+ : null;
55
+
56
+ return {
57
+ threadID: threadID,
58
+ threadName: messageThread.name,
59
+ participantIDs: messageThread.all_participants.edges.map(
60
+ (d) => d.node.messaging_actor.id,
61
+ ),
62
+ userInfo: messageThread.all_participants.edges.map((d) => ({
63
+ id: d.node.messaging_actor.id,
64
+ name: d.node.messaging_actor.name,
65
+ firstName: d.node.messaging_actor.short_name,
66
+ vanity: d.node.messaging_actor.username,
67
+ url: d.node.messaging_actor.url,
68
+ thumbSrc: d.node.messaging_actor.big_image_src.uri,
69
+ profileUrl: d.node.messaging_actor.big_image_src.uri,
70
+ gender: d.node.messaging_actor.gender,
71
+ type: d.node.messaging_actor.__typename,
72
+ isFriend: d.node.messaging_actor.is_viewer_friend,
73
+ isBirthday: !!d.node.messaging_actor.is_birthday, //not sure?
74
+ })),
75
+ unreadCount: messageThread.unread_count,
76
+ messageCount: messageThread.messages_count,
77
+ timestamp: messageThread.updated_time_precise,
78
+ muteUntil: messageThread.mute_until,
79
+ isGroup: messageThread.thread_type == "GROUP",
80
+ isSubscribed: messageThread.is_viewer_subscribed,
81
+ isArchived: messageThread.has_viewer_archived,
82
+ folder: messageThread.folder,
83
+ cannotReplyReason: messageThread.cannot_reply_reason,
84
+ eventReminders: messageThread.event_reminders
85
+ ? messageThread.event_reminders.nodes.map(formatEventReminders)
86
+ : null,
87
+ emoji: messageThread.customization_info
88
+ ? messageThread.customization_info.emoji
89
+ : null,
90
+ color:
91
+ messageThread.customization_info &&
92
+ messageThread.customization_info.outgoing_bubble_color
93
+ ? messageThread.customization_info.outgoing_bubble_color.slice(2)
94
+ : null,
95
+ threadTheme: messageThread.thread_theme,
96
+ nicknames:
97
+ messageThread.customization_info &&
98
+ messageThread.customization_info.participant_customizations
99
+ ? messageThread.customization_info.participant_customizations.reduce(
100
+ function (res, val) {
101
+ if (val.nickname) res[val.participant_id] = val.nickname;
102
+ return res;
103
+ },
104
+ {},
105
+ )
106
+ : {},
107
+ adminIDs: messageThread.thread_admins,
108
+ approvalMode: Boolean(messageThread.approval_mode),
109
+ approvalQueue: messageThread.group_approval_queue.nodes.map((a) => ({
110
+ inviterID: a.inviter.id,
111
+ requesterID: a.requester.id,
112
+ timestamp: a.request_timestamp,
113
+ request_source: a.request_source, // @Undocumented
114
+ })),
115
+
116
+ // @Undocumented
117
+ reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
118
+ mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
119
+ isPinProtected: messageThread.is_pin_protected,
120
+ relatedPageThread: messageThread.related_page_thread,
121
+
122
+ // @Legacy
123
+ name: messageThread.name,
124
+ snippet: snippetText,
125
+ snippetSender: snippetID,
126
+ snippetAttachments: [],
127
+ serverTimestamp: messageThread.updated_time_precise,
128
+ imageSrc: messageThread.image ? messageThread.image.uri : null,
129
+ isCanonicalUser: messageThread.is_canonical_neo_user,
130
+ isCanonical: messageThread.thread_type != "GROUP",
131
+ recipientsLoadable: true,
132
+ hasEmailParticipant: false,
133
+ readOnly: false,
134
+ canReply: messageThread.cannot_reply_reason == null,
135
+ lastMessageTimestamp: messageThread.last_message
136
+ ? messageThread.last_message.timestamp_precise
137
+ : null,
138
+ lastMessageType: "message",
139
+ lastReadTimestamp: lastReadTimestamp,
140
+ threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
141
+
142
+ // update in Wed, 13 Jul 2022 19:41:12 +0700
143
+ inviteLink: {
144
+ enable: messageThread.joinable_mode
145
+ ? messageThread.joinable_mode.mode == 1
146
+ : false,
147
+ link: messageThread.joinable_mode
148
+ ? messageThread.joinable_mode.link
149
+ : null,
150
+ },
151
+ };
152
+ }
153
+
154
+ function formatThreadList(data) {
155
+ // console.log(JSON.stringify(data.find(t => t.thread_key.thread_fbid === "5095817367161431"), null, 2));
156
+ return data.map((t) => formatThreadGraphQLResponse(t));
157
+ }
158
+
159
+ module.exports = function (defaultFuncs, api, ctx) {
160
+ return function getThreadList(limit, timestamp, tags, callback) {
161
+ if (
162
+ !callback &&
163
+ (utils.getType(tags) === "Function" ||
164
+ utils.getType(tags) === "AsyncFunction")
165
+ ) {
166
+ callback = tags;
167
+ tags = [""];
168
+ }
169
+ if (
170
+ utils.getType(limit) !== "Number" ||
171
+ !Number.isInteger(limit) ||
172
+ limit <= 0
173
+ ) {
174
+ throw new utils.CustomError({
175
+ error: "getThreadList: limit must be a positive integer",
176
+ });
177
+ }
178
+ if (
179
+ utils.getType(timestamp) !== "Null" &&
180
+ (utils.getType(timestamp) !== "Number" || !Number.isInteger(timestamp))
181
+ ) {
182
+ throw new utils.CustomError({
183
+ error: "getThreadList: timestamp must be an integer or null",
184
+ });
185
+ }
186
+ if (utils.getType(tags) === "String") {
187
+ tags = [tags];
188
+ }
189
+ if (utils.getType(tags) !== "Array") {
190
+ throw new utils.CustomError({
191
+ error: "getThreadList: tags must be an array",
192
+ message: "getThreadList: tags must be an array",
193
+ });
194
+ }
195
+
196
+ let resolveFunc = function () {};
197
+ let rejectFunc = function () {};
198
+ const returnPromise = new Promise(function (resolve, reject) {
199
+ resolveFunc = resolve;
200
+ rejectFunc = reject;
201
+ });
202
+
203
+ if (
204
+ utils.getType(callback) !== "Function" &&
205
+ utils.getType(callback) !== "AsyncFunction"
206
+ ) {
207
+ callback = function (err, data) {
208
+ if (err) {
209
+ return rejectFunc(err);
210
+ }
211
+ resolveFunc(data);
212
+ };
213
+ }
214
+
215
+ const form = {
216
+ av: ctx.userID,
217
+ queries: JSON.stringify({
218
+ o0: {
219
+ // This doc_id was valid on 2020-07-20
220
+ // "doc_id": "3336396659757871",
221
+ doc_id: "3426149104143726",
222
+ query_params: {
223
+ limit: limit + (timestamp ? 1 : 0),
224
+ before: timestamp,
225
+ tags: tags,
226
+ includeDeliveryReceipts: true,
227
+ includeSeqID: false,
228
+ },
229
+ },
230
+ }),
231
+ batch_name: "MessengerGraphQLThreadlistFetcher",
232
+ };
233
+
234
+ defaultFuncs
235
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
236
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
237
+ .then((resData) => {
238
+ if (resData[resData.length - 1].error_results > 0) {
239
+ throw new utils.CustomError(resData[0].o0.errors);
240
+ }
241
+
242
+ if (resData[resData.length - 1].successful_results === 0) {
243
+ throw new utils.CustomError({
244
+ error: "getThreadList: there was no successful_results",
245
+ res: resData,
246
+ });
247
+ }
248
+
249
+ // When we ask for threads using timestamp from the previous request,
250
+ // we are getting the last thread repeated as the first thread in this response.
251
+ // .shift() gets rid of it
252
+ // It is also the reason for increasing limit by 1 when timestamp is set
253
+ // this way user asks for 10 threads, we are asking for 11,
254
+ // but after removing the duplicated one, it is again 10
255
+ if (timestamp) {
256
+ resData[0].o0.data.viewer.message_threads.nodes.shift();
257
+ }
258
+ callback(
259
+ null,
260
+ formatThreadList(resData[0].o0.data.viewer.message_threads.nodes),
261
+ );
262
+ })
263
+ .catch((err) => {
264
+ console.error("getThreadList", err);
265
+ return callback(err);
266
+ });
267
+
268
+ return returnPromise;
269
+ };
270
+ };