@lazyneoaz/nkxchat 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 (123) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +199 -0
  3. package/examples/login-with-cookies.js +102 -0
  4. package/examples/verify.js +70 -0
  5. package/index.js +2 -0
  6. package/package.json +84 -0
  7. package/src/apis/addExternalModule.js +24 -0
  8. package/src/apis/addUserToGroup.js +108 -0
  9. package/src/apis/changeAdminStatus.js +148 -0
  10. package/src/apis/changeArchivedStatus.js +61 -0
  11. package/src/apis/changeAvatar.js +103 -0
  12. package/src/apis/changeBio.js +69 -0
  13. package/src/apis/changeBlockedStatus.js +54 -0
  14. package/src/apis/changeGroupImage.js +136 -0
  15. package/src/apis/changeThreadColor.js +116 -0
  16. package/src/apis/changeThreadEmoji.js +53 -0
  17. package/src/apis/comment.js +207 -0
  18. package/src/apis/createAITheme.js +129 -0
  19. package/src/apis/createNewGroup.js +79 -0
  20. package/src/apis/createPoll.js +73 -0
  21. package/src/apis/deleteMessage.js +44 -0
  22. package/src/apis/deleteThread.js +52 -0
  23. package/src/apis/editMessage.js +70 -0
  24. package/src/apis/emoji.js +124 -0
  25. package/src/apis/enableAutoSaveAppState.js +69 -0
  26. package/src/apis/fetchThemeData.js +113 -0
  27. package/src/apis/follow.js +81 -0
  28. package/src/apis/forwardAttachment.js +178 -0
  29. package/src/apis/forwardMessage.js +52 -0
  30. package/src/apis/friend.js +243 -0
  31. package/src/apis/gcmember.js +122 -0
  32. package/src/apis/gcname.js +123 -0
  33. package/src/apis/gcrule.js +119 -0
  34. package/src/apis/getAccess.js +111 -0
  35. package/src/apis/getBotInfo.js +88 -0
  36. package/src/apis/getBotInitialData.js +43 -0
  37. package/src/apis/getEmojiUrl.js +40 -0
  38. package/src/apis/getFriendsList.js +79 -0
  39. package/src/apis/getMessage.js +423 -0
  40. package/src/apis/getTheme.js +123 -0
  41. package/src/apis/getThemeInfo.js +116 -0
  42. package/src/apis/getThemePictures.js +87 -0
  43. package/src/apis/getThreadColors.js +119 -0
  44. package/src/apis/getThreadHistory.js +239 -0
  45. package/src/apis/getThreadInfo.js +267 -0
  46. package/src/apis/getThreadList.js +232 -0
  47. package/src/apis/getThreadPictures.js +58 -0
  48. package/src/apis/getUserID.js +117 -0
  49. package/src/apis/getUserInfo.js +513 -0
  50. package/src/apis/getUserInfoV2.js +146 -0
  51. package/src/apis/handleFriendRequest.js +66 -0
  52. package/src/apis/handleMessageRequest.js +50 -0
  53. package/src/apis/httpGet.js +63 -0
  54. package/src/apis/httpPost.js +89 -0
  55. package/src/apis/httpPostFormData.js +69 -0
  56. package/src/apis/listenMqtt.js +924 -0
  57. package/src/apis/listenSpeed.js +178 -0
  58. package/src/apis/logout.js +63 -0
  59. package/src/apis/markAsDelivered.js +47 -0
  60. package/src/apis/markAsRead.js +95 -0
  61. package/src/apis/markAsReadAll.js +40 -0
  62. package/src/apis/markAsSeen.js +70 -0
  63. package/src/apis/mqttDeltaValue.js +252 -0
  64. package/src/apis/muteThread.js +45 -0
  65. package/src/apis/nickname.js +132 -0
  66. package/src/apis/notes.js +163 -0
  67. package/src/apis/pinMessage.js +150 -0
  68. package/src/apis/produceMetaTheme.js +160 -0
  69. package/src/apis/realtime.js +182 -0
  70. package/src/apis/refreshFb_dtsg.js +94 -0
  71. package/src/apis/removeUserFromGroup.js +117 -0
  72. package/src/apis/resolvePhotoUrl.js +58 -0
  73. package/src/apis/searchForThread.js +154 -0
  74. package/src/apis/sendEffect.js +306 -0
  75. package/src/apis/sendMessage.js +353 -0
  76. package/src/apis/sendMessageMqtt.js +255 -0
  77. package/src/apis/sendTypingIndicator.js +40 -0
  78. package/src/apis/setMessageReaction.js +27 -0
  79. package/src/apis/setMessageReactionMqtt.js +61 -0
  80. package/src/apis/setPostReaction.js +118 -0
  81. package/src/apis/setThreadTheme.js +210 -0
  82. package/src/apis/setThreadThemeMqtt.js +94 -0
  83. package/src/apis/setTitle.js +26 -0
  84. package/src/apis/share.js +106 -0
  85. package/src/apis/shareContact.js +66 -0
  86. package/src/apis/stickers.js +257 -0
  87. package/src/apis/story.js +181 -0
  88. package/src/apis/theme.js +233 -0
  89. package/src/apis/unfriend.js +47 -0
  90. package/src/apis/unsendMessage.js +17 -0
  91. package/src/apis/uploadAttachment.js +87 -0
  92. package/src/database/appStateBackup.js +189 -0
  93. package/src/database/models/index.js +56 -0
  94. package/src/database/models/thread.js +31 -0
  95. package/src/database/models/user.js +32 -0
  96. package/src/database/threadData.js +101 -0
  97. package/src/database/userData.js +90 -0
  98. package/src/engine/client.js +92 -0
  99. package/src/engine/models/buildAPI.js +118 -0
  100. package/src/engine/models/loginHelper.js +492 -0
  101. package/src/engine/models/setOptions.js +88 -0
  102. package/src/types/index.d.ts +498 -0
  103. package/src/utils/antiSuspension.js +516 -0
  104. package/src/utils/auth-helpers.js +149 -0
  105. package/src/utils/autoReLogin.js +237 -0
  106. package/src/utils/axios.js +368 -0
  107. package/src/utils/cache.js +54 -0
  108. package/src/utils/clients.js +279 -0
  109. package/src/utils/constants.js +525 -0
  110. package/src/utils/formatters/data/formatAttachment.js +370 -0
  111. package/src/utils/formatters/data/formatDelta.js +109 -0
  112. package/src/utils/formatters/index.js +159 -0
  113. package/src/utils/formatters/value/formatCookie.js +91 -0
  114. package/src/utils/formatters/value/formatDate.js +36 -0
  115. package/src/utils/formatters/value/formatID.js +16 -0
  116. package/src/utils/formatters.js +1369 -0
  117. package/src/utils/headers.js +235 -0
  118. package/src/utils/index.js +152 -0
  119. package/src/utils/monitoring.js +333 -0
  120. package/src/utils/rateLimiter.js +251 -0
  121. package/src/utils/tokenRefresh.js +285 -0
  122. package/src/utils/user-agents.js +238 -0
  123. package/src/utils/validation.js +157 -0
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+
5
+ /**
6
+ * Fetches theme asset images (background, icon, previews) for a given theme ID.
7
+ * Uses the MWPThreadThemeProviderQuery GraphQL endpoint — the same doc_id used
8
+ * by fetchThemeData, but returns the raw full response so callers get every asset field.
9
+ *
10
+ * @param {string} id Numeric theme ID (e.g. "196241301102133").
11
+ * @param {Function} [callback]
12
+ * @returns {Promise<object>} Full theme provider response including all image assets.
13
+ */
14
+ module.exports = function (defaultFuncs, api, ctx) {
15
+ return function getThemePictures(id, callback) {
16
+ let resolveFunc, rejectFunc;
17
+ const promise = new Promise((resolve, reject) => {
18
+ resolveFunc = resolve;
19
+ rejectFunc = reject;
20
+ });
21
+
22
+ const done = callback || function (err, data) {
23
+ if (err) return rejectFunc(err);
24
+ resolveFunc(data);
25
+ };
26
+
27
+ if (!id) {
28
+ done(new Error("theme id is required"));
29
+ return promise;
30
+ }
31
+
32
+ const normalizedId = String(id);
33
+
34
+ const form = {
35
+ av: ctx.userID,
36
+ __user: ctx.userID,
37
+ __a: 1,
38
+ __req: utils.getSignatureID(),
39
+ fb_dtsg: ctx.fb_dtsg,
40
+ lsd: ctx.lsd || ctx.fb_dtsg,
41
+ jazoest: ctx.jazoest,
42
+ fb_api_caller_class: "RelayModern",
43
+ fb_api_req_friendly_name: "MWPThreadThemeProviderQuery",
44
+ doc_id: "9734829906576883",
45
+ server_timestamps: true,
46
+ variables: JSON.stringify({ id: normalizedId }),
47
+ };
48
+
49
+ defaultFuncs
50
+ .post("https://www.facebook.com/api/graphql/", ctx.jar, form)
51
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
52
+ .then((resData) => {
53
+ if (resData && resData.errors) throw resData;
54
+
55
+ const themeData = resData && resData.data && resData.data.messenger_thread_theme;
56
+
57
+ const extractUri = (obj) => (obj && obj.image && obj.image.uri) || null;
58
+
59
+ const result = {
60
+ id: normalizedId,
61
+ raw: resData,
62
+ theme: themeData || null,
63
+ backgroundImage: extractUri(themeData && themeData.background_asset),
64
+ iconImage: extractUri(themeData && themeData.icon_asset),
65
+ name: themeData ? (themeData.accessibility_label || themeData.name || "") : "",
66
+ gradient_colors: themeData ? (themeData.gradient_colors || []) : [],
67
+ fallback_color: themeData ? (themeData.fallback_color || null) : null,
68
+ alternative_themes: themeData && Array.isArray(themeData.alternative_themes)
69
+ ? themeData.alternative_themes.map(a => ({
70
+ id: a.id,
71
+ backgroundImage: extractUri(a.background_asset),
72
+ iconImage: extractUri(a.icon_asset),
73
+ gradient_colors: a.gradient_colors || [],
74
+ }))
75
+ : [],
76
+ };
77
+
78
+ done(null, result);
79
+ })
80
+ .catch((err) => {
81
+ utils.error("getThemePictures", err.message || err);
82
+ done(err instanceof Error ? err : new Error(String(err.message || err)));
83
+ });
84
+
85
+ return promise;
86
+ };
87
+ };
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * All known Messenger thread color theme IDs.
5
+ * Keys are human-readable names; values are Facebook's numeric theme_fbid strings.
6
+ *
7
+ * Use api.changeThreadColor(id, threadID) or api.setThreadThemeMqtt(threadID, id)
8
+ * to apply one of these colors.
9
+ */
10
+ const THREAD_COLORS = {
11
+ // ── Core palette ─────────────────────────────────────────────────
12
+ MessengerBlue: "196241301102133",
13
+ DefaultBlue: "196241301102133",
14
+ Default: "3259963564026002",
15
+ Viking: "1928399724138152",
16
+ TealBlue: "1928399724138152",
17
+ GoldenPoppy: "174636906462322",
18
+ Yellow: "174636906462322",
19
+ RadicalRed: "2129984390566328",
20
+ Red: "2129984390566328",
21
+ Shocking: "2058653964378557",
22
+ LavenderPurple: "2058653964378557",
23
+ FreeSpeechGreen: "2136751179887052",
24
+ Green: "2136751179887052",
25
+ Pumpkin: "175615189761153",
26
+ Orange: "175615189761153",
27
+ LightCoral: "980963458735625",
28
+ CoralPink: "980963458735625",
29
+ MediumSlateBlue: "234137870477637",
30
+ BrightPurple: "234137870477637",
31
+ DeepSkyBlue: "2442142322678320",
32
+ AquaBlue: "2442142322678320",
33
+ BrilliantRose: "169463077092846",
34
+ HotPink: "169463077092846",
35
+ Aqua: "417639218648241",
36
+ // ── Named themes ─────────────────────────────────────────────────
37
+ Mango: "930060997172551",
38
+ Berry: "164535220883264",
39
+ Berry2: "724096885023603",
40
+ Citrus: "370940413392601",
41
+ Citrus2: "557344741607350",
42
+ Candy: "205488546921017",
43
+ Candy2: "624266884847972",
44
+ Earth: "1833559466821043",
45
+ Support: "365557122117011",
46
+ Music: "339021464972092",
47
+ Pride: "1652456634878319",
48
+ DoctorStrange: "538280997628317",
49
+ LoFi: "1060619084701625",
50
+ Sky: "3190514984517598",
51
+ LunarNewYear: "357833546030778",
52
+ Celebration: "627144732056021",
53
+ Chill: "390127158985345",
54
+ StrangerThings: "1059859811490132",
55
+ Dune: "1455149831518874",
56
+ Care: "275041734441112",
57
+ Astrology: "3082966625307060",
58
+ JBalvin: "184305226956268",
59
+ Birthday: "621630955405500",
60
+ Cottagecore: "539927563794799",
61
+ Ocean: "736591620215564",
62
+ Love: "741311439775765",
63
+ TieDye: "230032715012014",
64
+ Monochrome: "788274591712841",
65
+ Rocket: "582065306070020",
66
+ Unicorn: "273728810607574",
67
+ Tropical: "262191918210707",
68
+ Maple: "2533652183614000",
69
+ Sushi: "909695489504566",
70
+ Lollipop: "280333826736184",
71
+ Shadow: "271607034185782",
72
+ Rose: "1257453361255152",
73
+ Lavender: "571193503540759",
74
+ Tulip: "2873642949430623",
75
+ Classic: "3273938616164733",
76
+ Peach: "3022526817824329",
77
+ Honey: "672058580051520",
78
+ Kiwi: "3151463484918004",
79
+ Grape: "193497045377796",
80
+ // ── Special / seasonal ───────────────────────────────────────────
81
+ NonBinary: "737761000603635",
82
+ ThankfulForFriends: "1318983195536293",
83
+ Transgender: "504518465021637",
84
+ TaylorSwift: "769129927636836",
85
+ NationalComingOutDay: "788102625833584",
86
+ Autumn: "822549609168155",
87
+ Cyberpunk2077: "780962576430091",
88
+ MothersDay: "1288506208402340",
89
+ APAHM: "121771470870245",
90
+ Parenthood: "810978360551741",
91
+ StarWars: "1438011086532622",
92
+ GuardianOfTheGalaxy: "101275642962533",
93
+ Bloom: "158263147151440",
94
+ BubbleTea: "195296273246380",
95
+ Basketball: "6026716157422736",
96
+ ElephantsAndFlowers: "693996545771691",
97
+ };
98
+
99
+ module.exports = function (defaultFuncs, api, ctx) {
100
+ /**
101
+ * Returns all available thread color themes.
102
+ *
103
+ * @param {string} [query] Optional fuzzy search term. If provided, returns only
104
+ * themes whose name contains the query (case-insensitive).
105
+ * @returns {Object|Array}
106
+ * - Without query: plain object { name → id }
107
+ * - With query: array of { name, id } matches
108
+ */
109
+ return function getThreadColors(query) {
110
+ if (!query) {
111
+ return { ...THREAD_COLORS };
112
+ }
113
+
114
+ const q = String(query).toLowerCase();
115
+ return Object.entries(THREAD_COLORS)
116
+ .filter(([name]) => name.toLowerCase().includes(q))
117
+ .map(([name, id]) => ({ name, id }));
118
+ };
119
+ };
@@ -0,0 +1,239 @@
1
+ "use strict";
2
+
3
+ const utils = require('../utils');
4
+
5
+
6
+ /**
7
+ * Formats a single attachment object from a GraphQL response.
8
+ * @param {Object} attachment The raw attachment object.
9
+ * @returns {Object} A formatted attachment object.
10
+ */
11
+ function formatAttachmentsGraphQLResponse(attachment) {
12
+ switch (attachment.__typename) {
13
+ case "MessageImage":
14
+ return {
15
+ type: "photo",
16
+ ID: attachment.legacy_attachment_id,
17
+ filename: attachment.filename,
18
+ thumbnailUrl: attachment.thumbnail.uri,
19
+ previewUrl: attachment.preview.uri,
20
+ previewWidth: attachment.preview.width,
21
+ previewHeight: attachment.preview.height,
22
+ largePreviewUrl: attachment.large_preview.uri,
23
+ largePreviewHeight: attachment.large_preview.height,
24
+ largePreviewWidth: attachment.large_preview.width,
25
+ url: attachment.large_preview.uri,
26
+ width: attachment.original_dimensions.x,
27
+ height: attachment.original_dimensions.y,
28
+ name: attachment.filename
29
+ };
30
+ case "MessageAnimatedImage":
31
+ return {
32
+ type: "animated_image",
33
+ ID: attachment.legacy_attachment_id,
34
+ filename: attachment.filename,
35
+ previewUrl: attachment.preview_image.uri,
36
+ previewWidth: attachment.preview_image.width,
37
+ previewHeight: attachment.preview_image.height,
38
+ url: attachment.animated_image.uri,
39
+ width: attachment.animated_image.width,
40
+ height: attachment.animated_image.height,
41
+ name: attachment.filename,
42
+ facebookUrl: attachment.animated_image.uri,
43
+ };
44
+ case "MessageVideo":
45
+ return {
46
+ type: "video",
47
+ ID: attachment.legacy_attachment_id,
48
+ filename: attachment.filename,
49
+ duration: attachment.playable_duration_in_ms,
50
+ thumbnailUrl: attachment.large_image.uri,
51
+ previewUrl: attachment.large_image.uri,
52
+ previewWidth: attachment.large_image.width,
53
+ previewHeight: attachment.large_image.height,
54
+ url: attachment.playable_url,
55
+ width: attachment.original_dimensions.x,
56
+ height: attachment.original_dimensions.y,
57
+ videoType: attachment.video_type.toLowerCase(),
58
+ };
59
+ case "MessageFile":
60
+ return {
61
+ type: "file",
62
+ ID: attachment.message_file_fbid,
63
+ filename: attachment.filename,
64
+ url: attachment.url,
65
+ isMalicious: attachment.is_malicious,
66
+ contentType: attachment.content_type,
67
+ name: attachment.filename,
68
+ };
69
+ case "MessageAudio":
70
+ return {
71
+ type: "audio",
72
+ ID: attachment.url_shimhash,
73
+ filename: attachment.filename,
74
+ duration: attachment.playable_duration_in_ms,
75
+ audioType: attachment.audio_type,
76
+ url: attachment.playable_url,
77
+ isVoiceMail: attachment.is_voicemail,
78
+ };
79
+ default:
80
+ return {
81
+ type: "unknown",
82
+ error: "Don't know about attachment type " + attachment.__typename,
83
+ };
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Formats a share (extensible) attachment from a GraphQL response.
89
+ * @param {Object} attachment The raw extensible attachment object.
90
+ * @returns {Object} A formatted share attachment object.
91
+ */
92
+ function formatExtensibleAttachment(attachment) {
93
+ if (attachment.story_attachment) {
94
+ return {
95
+ type: "share",
96
+ ID: attachment.legacy_attachment_id,
97
+ url: attachment.story_attachment.url,
98
+ title: attachment.story_attachment.title_with_entities.text,
99
+ description: attachment.story_attachment.description && attachment.story_attachment.description.text,
100
+ source: attachment.story_attachment.source == null ? null : attachment.story_attachment.source.text,
101
+ image: attachment.story_attachment.media?.image?.uri,
102
+ width: attachment.story_attachment.media?.image?.width,
103
+ height: attachment.story_attachment.media?.image?.height,
104
+ playable: attachment.story_attachment.media?.is_playable,
105
+ duration: attachment.story_attachment.media?.playable_duration_in_ms,
106
+ playableUrl: attachment.story_attachment.media?.playable_url,
107
+ subattachments: attachment.story_attachment.subattachments,
108
+ properties: attachment.story_attachment.properties.reduce((obj, cur) => {
109
+ obj[cur.key] = cur.value.text;
110
+ return obj;
111
+ }, {}),
112
+ };
113
+ }
114
+ return { type: "unknown", error: "Don't know what to do with extensible_attachment." };
115
+ }
116
+
117
+ /**
118
+ * Formats the response from a GraphQL message history query.
119
+ * @param {Object} data The raw GraphQL response data.
120
+ * @returns {Array<Object>} An array of formatted message objects.
121
+ */
122
+ function formatMessagesGraphQLResponse(data) {
123
+ const messageThread = data.o0.data.message_thread;
124
+ if (!messageThread) return [];
125
+
126
+ const threadID = messageThread.thread_key.thread_fbid ? messageThread.thread_key.thread_fbid : messageThread.thread_key.other_user_id;
127
+
128
+ return messageThread.messages.nodes.map(d => {
129
+ switch (d.__typename) {
130
+ case "UserMessage":
131
+ const mentions = {};
132
+ if (d.message?.ranges) {
133
+ d.message.ranges.forEach(e => {
134
+ mentions[e.entity.id] = d.message.text.substring(e.offset, e.offset + e.length);
135
+ });
136
+ }
137
+ return {
138
+ type: "message",
139
+ attachments: d.sticker ? [{
140
+ type: "sticker",
141
+ ID: d.sticker.id,
142
+ url: d.sticker.url,
143
+ packID: d.sticker.pack?.id,
144
+ frameCount: d.sticker.frame_count,
145
+ frameRate: d.sticker.frame_rate,
146
+ framesPerRow: d.sticker.frames_per_row,
147
+ framesPerCol: d.sticker.frames_per_col,
148
+ stickerID: d.sticker.id,
149
+ }] : (d.blob_attachments || []).map(formatAttachmentsGraphQLResponse).concat(d.extensible_attachment ? [formatExtensibleAttachment(d.extensible_attachment)] : []),
150
+ body: d.message?.text || "",
151
+ isGroup: messageThread.thread_type === "GROUP",
152
+ messageID: d.message_id,
153
+ senderID: d.message_sender.id,
154
+ threadID: threadID,
155
+ timestamp: d.timestamp_precise,
156
+ mentions: mentions,
157
+ isUnread: d.unread,
158
+ messageReactions: d.message_reactions?.map(r => ({ reaction: r.reaction, userID: r.user.id })) || [],
159
+ };
160
+ case "ThreadNameMessage":
161
+ case "ThreadImageMessage":
162
+ case "ParticipantLeftMessage":
163
+ case "ParticipantsAddedMessage":
164
+ case "GenericAdminTextMessage": {
165
+
166
+
167
+ return {
168
+ type: "event",
169
+ messageID: d.message_id,
170
+ threadID: threadID,
171
+ isGroup: messageThread.thread_type === "GROUP",
172
+ senderID: d.message_sender.id,
173
+ author: d.message_sender.id,
174
+ timestamp: d.timestamp_precise,
175
+ snippet: d.snippet,
176
+ logMessageType: utils.getAdminTextMessageType(d.extensible_message_admin_text_type || d.__typename),
177
+ logMessageData: d.extensible_message_admin_text || d,
178
+ };
179
+ }
180
+ default:
181
+ return { type: "unknown", error: "Unknown message type " + d.__typename, raw: d };
182
+ }
183
+ });
184
+ }
185
+
186
+ /**
187
+ * @param {Object} defaultFuncs
188
+ * @param {Object} api
189
+ * @param {Object} ctx
190
+ * @returns {function(threadID: string, amount: number, timestamp: number | null): Promise<Array<Object>>}
191
+ */
192
+ module.exports = function (defaultFuncs, api, ctx) {
193
+ /**
194
+ * Retrieves the message history for a specific thread.
195
+ * @param {string} threadID The ID of the thread to fetch history from.
196
+ * @param {number} amount The number of messages to retrieve.
197
+ * @param {number | null} timestamp The timestamp to start fetching messages before.
198
+ * @returns {Promise<Array<Object>>} A promise that resolves with an array of formatted message objects.
199
+ */
200
+ return async function getThreadHistory(threadID, amount, timestamp) {
201
+ if (!threadID || !amount) {
202
+ throw new Error("getThreadHistory: threadID and amount are required.");
203
+ }
204
+
205
+ const form = {
206
+ av: ctx.globalOptions.pageID,
207
+ queries: JSON.stringify({
208
+ o0: {
209
+ doc_id: "1498317363570230",
210
+ query_params: {
211
+ id: threadID,
212
+ message_limit: amount,
213
+ load_messages: 1,
214
+ load_read_receipts: false,
215
+ before: timestamp || null,
216
+ },
217
+ },
218
+ }),
219
+ };
220
+
221
+ try {
222
+ const resData = await defaultFuncs.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form);
223
+ const parsedData = await utils.parseAndCheckLogin(ctx, defaultFuncs)(resData);
224
+
225
+ if (parsedData.error || (Array.isArray(parsedData) && parsedData[parsedData.length - 1].error_results !== 0)) {
226
+ throw parsedData;
227
+ }
228
+
229
+ if (!Array.isArray(parsedData) || !parsedData[0] || !parsedData[0].o0 || !parsedData[0].o0.data) {
230
+ throw { error: "getThreadHistory: Malformed response from GraphQL.", res: parsedData };
231
+ }
232
+
233
+ return formatMessagesGraphQLResponse(parsedData[0]);
234
+ } catch (err) {
235
+ utils.error("getThreadHistory", err);
236
+ throw err;
237
+ }
238
+ };
239
+ };