@cexy/hoonfca 1.0.0 → 1.0.1

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 (188) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +451 -43
  3. package/examples/login-with-cookies.js +102 -0
  4. package/examples/verify.js +70 -0
  5. package/index.js +1 -466
  6. package/package.json +98 -6
  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/{changeThreadEmoji.js → apis/changeThreadEmoji.js} +7 -8
  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/e2ee.js +17 -0
  24. package/src/apis/editMessage.js +70 -0
  25. package/src/apis/emoji.js +124 -0
  26. package/src/apis/fetchThemeData.js +82 -0
  27. package/src/apis/follow.js +81 -0
  28. package/src/apis/forwardMessage.js +52 -0
  29. package/src/apis/friend.js +243 -0
  30. package/src/apis/gcmember.js +122 -0
  31. package/src/apis/gcname.js +123 -0
  32. package/src/apis/gcrule.js +119 -0
  33. package/src/apis/getAccess.js +111 -0
  34. package/src/apis/getBotInfo.js +88 -0
  35. package/src/apis/getBotInitialData.js +43 -0
  36. package/src/apis/getFriendsList.js +79 -0
  37. package/src/apis/getMessage.js +423 -0
  38. package/src/apis/getTheme.js +95 -0
  39. package/src/apis/getThemeInfo.js +116 -0
  40. package/src/apis/getThreadHistory.js +239 -0
  41. package/src/apis/getThreadInfo.js +267 -0
  42. package/src/apis/getThreadList.js +232 -0
  43. package/src/apis/getThreadPictures.js +58 -0
  44. package/src/apis/getUserID.js +117 -0
  45. package/src/apis/getUserInfo.js +513 -0
  46. package/src/apis/getUserInfoV2.js +146 -0
  47. package/src/apis/handleMessageRequest.js +50 -0
  48. package/src/apis/httpGet.js +63 -0
  49. package/src/apis/httpPost.js +89 -0
  50. package/src/apis/httpPostFormData.js +69 -0
  51. package/src/apis/listenMqtt.js +1236 -0
  52. package/src/apis/listenSpeed.js +179 -0
  53. package/src/apis/logout.js +87 -0
  54. package/src/apis/markAsDelivered.js +47 -0
  55. package/src/apis/markAsRead.js +99 -0
  56. package/src/apis/markAsReadAll.js +40 -0
  57. package/src/apis/markAsSeen.js +70 -0
  58. package/src/apis/mqttDeltaValue.js +278 -0
  59. package/src/apis/muteThread.js +45 -0
  60. package/src/apis/nickname.js +132 -0
  61. package/src/apis/notes.js +163 -0
  62. package/src/apis/pinMessage.js +150 -0
  63. package/src/apis/produceMetaTheme.js +180 -0
  64. package/src/apis/realtime.js +182 -0
  65. package/src/apis/removeUserFromGroup.js +117 -0
  66. package/src/apis/resolvePhotoUrl.js +58 -0
  67. package/src/apis/searchForThread.js +154 -0
  68. package/src/apis/sendMessage.js +354 -0
  69. package/src/apis/sendMessageMqtt.js +249 -0
  70. package/src/apis/sendTypingIndicator.js +91 -0
  71. package/src/apis/setMessageReaction.js +27 -0
  72. package/src/apis/setMessageReactionMqtt.js +61 -0
  73. package/src/apis/setThreadTheme.js +260 -0
  74. package/src/apis/setThreadThemeMqtt.js +94 -0
  75. package/src/apis/share.js +107 -0
  76. package/src/apis/shareContact.js +66 -0
  77. package/src/apis/stickers.js +257 -0
  78. package/src/apis/story.js +181 -0
  79. package/src/apis/theme.js +233 -0
  80. package/src/apis/unfriend.js +47 -0
  81. package/src/apis/unsendMessage.js +17 -0
  82. package/src/engine/client.js +92 -0
  83. package/src/engine/models/buildAPI.js +152 -0
  84. package/src/engine/models/loginHelper.js +519 -0
  85. package/src/engine/models/setOptions.js +88 -0
  86. package/src/security/e2ee.js +109 -0
  87. package/src/types/index.d.ts +498 -0
  88. package/src/utils/antiSuspension.js +506 -0
  89. package/src/utils/auth-helpers.js +149 -0
  90. package/src/utils/autoReLogin.js +336 -0
  91. package/src/utils/axios.js +436 -0
  92. package/src/utils/cache.js +54 -0
  93. package/src/utils/clients.js +282 -0
  94. package/src/utils/constants.js +410 -0
  95. package/src/utils/formatters/data/formatAttachment.js +370 -0
  96. package/src/utils/formatters/data/formatDelta.js +109 -0
  97. package/src/utils/formatters/index.js +159 -0
  98. package/src/utils/formatters/value/formatCookie.js +91 -0
  99. package/src/utils/formatters/value/formatDate.js +36 -0
  100. package/src/utils/formatters/value/formatID.js +16 -0
  101. package/src/utils/formatters.js +1373 -0
  102. package/src/utils/headers.js +230 -0
  103. package/src/utils/index.js +153 -0
  104. package/src/utils/monitoring.js +333 -0
  105. package/src/utils/rateLimiter.js +319 -0
  106. package/src/utils/tokenRefresh.js +657 -0
  107. package/src/utils/user-agents.js +238 -0
  108. package/src/utils/validation.js +157 -0
  109. package/replit.nix +0 -3
  110. package/src/addExternalModule.js +0 -25
  111. package/src/addUserToGroup.js +0 -98
  112. package/src/changeAdminStatus.js +0 -98
  113. package/src/changeArchivedStatus.js +0 -51
  114. package/src/changeAvatar.js +0 -89
  115. package/src/changeBio.js +0 -74
  116. package/src/changeBlockedStatus.js +0 -45
  117. package/src/changeBlockedStatusMqtt.js +0 -65
  118. package/src/changeCover.js +0 -92
  119. package/src/changeGroupImage.js +0 -110
  120. package/src/changeName.js +0 -106
  121. package/src/changeNickname.js +0 -58
  122. package/src/changeThreadColor.js +0 -62
  123. package/src/changeUsername.js +0 -80
  124. package/src/createCommentPost.js +0 -196
  125. package/src/createNewGroup.js +0 -81
  126. package/src/createPoll.js +0 -64
  127. package/src/createPost.js +0 -285
  128. package/src/data/getThreadInfo.json +0 -1
  129. package/src/deleteMessage.js +0 -55
  130. package/src/deleteThread.js +0 -55
  131. package/src/editMessage.js +0 -66
  132. package/src/follow.js +0 -71
  133. package/src/forwardAttachment.js +0 -57
  134. package/src/getAccess.js +0 -130
  135. package/src/getAvatarUser.js +0 -88
  136. package/src/getBotInitialData.js +0 -59
  137. package/src/getCtx.js +0 -5
  138. package/src/getCurrentUserID.js +0 -5
  139. package/src/getEmojiUrl.js +0 -18
  140. package/src/getFriendsList.js +0 -81
  141. package/src/getMessage.js +0 -827
  142. package/src/getOptions.js +0 -5
  143. package/src/getRegion.js +0 -7
  144. package/src/getThreadHistory.js +0 -496
  145. package/src/getThreadHistoryDeprecated.js +0 -95
  146. package/src/getThreadInfo.js +0 -194
  147. package/src/getThreadInfoDeprecated.js +0 -77
  148. package/src/getThreadList.js +0 -219
  149. package/src/getThreadListDeprecated.js +0 -86
  150. package/src/getThreadPictures.js +0 -85
  151. package/src/getUserID.js +0 -67
  152. package/src/getUserInfo.js +0 -89
  153. package/src/handleFriendRequest.js +0 -56
  154. package/src/handleMessageRequest.js +0 -65
  155. package/src/httpGet.js +0 -53
  156. package/src/httpPost.js +0 -53
  157. package/src/httpPostFormData.js +0 -58
  158. package/src/listenMqtt.js +0 -683
  159. package/src/listenNotification.js +0 -96
  160. package/src/logout.js +0 -77
  161. package/src/markAsDelivered.js +0 -53
  162. package/src/markAsRead.js +0 -74
  163. package/src/markAsReadAll.js +0 -46
  164. package/src/markAsSeen.js +0 -57
  165. package/src/muteThread.js +0 -49
  166. package/src/pinMessage.js +0 -60
  167. package/src/refreshFb_dtsg.js +0 -75
  168. package/src/removeUserFromGroup.js +0 -59
  169. package/src/resolvePhotoUrl.js +0 -47
  170. package/src/searchForThread.js +0 -55
  171. package/src/searchStickers.js +0 -59
  172. package/src/sendMessage.js +0 -444
  173. package/src/sendMessageMqtt.js +0 -326
  174. package/src/sendTypingIndicator.js +0 -54
  175. package/src/setMessageReaction.js +0 -126
  176. package/src/setMessageReactionMqtt.js +0 -74
  177. package/src/setPostReaction.js +0 -103
  178. package/src/setProfileGuard.js +0 -66
  179. package/src/setStoryReaction.js +0 -97
  180. package/src/setTitle.js +0 -100
  181. package/src/shareContact.js +0 -101
  182. package/src/shareLink.js +0 -105
  183. package/src/stopListenMqtt.js +0 -47
  184. package/src/threadColors.js +0 -119
  185. package/src/unfriend.js +0 -58
  186. package/src/unsendMessage.js +0 -51
  187. package/src/uploadAttachment.js +0 -98
  188. package/utils.js +0 -919
package/utils.js DELETED
@@ -1,919 +0,0 @@
1
- "use strict";
2
-
3
- const chalk = require("chalk");
4
- const gradient = require("gradient-string");
5
- const stream = require("stream");
6
- const querystring = require("querystring");
7
- const url = require("url");
8
-
9
- const echaceb = gradient(["#0061ff", "#681297"]);
10
- const ws = echaceb("ws3-fca");
11
-
12
- // Helper function first to prevent hoisting/undefined bugs
13
- function getType(obj) {
14
- return Object.prototype.toString.call(obj).slice(8, -1);
15
- }
16
-
17
- const getRandom = arr => arr[Math.floor(Math.random() * arr.length)];
18
- const defaultUserAgent = "facebookexternalhit/1.1";
19
- const windowsUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3";
20
-
21
- function randomUserAgent() {
22
- const platform = {
23
- platform: ['Windows NT 10.0; Win64; x64', 'Macintosh; Intel Mac OS X 14.7; rv:132.0'],
24
- browsers: {
25
- chrome: ['122.0.0.0', '121.0.0.0'],
26
- firefox: ['123.0', '122.0'],
27
- edge: ['122.0.2365.92']
28
- }
29
- };
30
- const browserName = getRandom(Object.keys(platform.browsers));
31
- const version = getRandom(platform.browsers[browserName]);
32
- const plat = getRandom(platform.platform);
33
- const userAgentArray = [
34
- defaultUserAgent,
35
- windowsUserAgent,
36
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15",
37
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:45.0) Gecko/20100101 Firefox/45.0",
38
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0",
39
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7",
40
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8",
41
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.3",
42
- ];
43
- return getRandom([
44
- browserName === 'firefox' ? `Mozilla/5.0 (${plat}) Gecko/20100101 Firefox/${version}` : `Mozilla/5.0 (${plat}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${version} Safari/537.36`,
45
- getRandom(userAgentArray)
46
- ]);
47
- }
48
-
49
- const headers = {
50
- "content-type": "application/x-www-form-urlencoded",
51
- "referer": "https://www.facebook.com/",
52
- "origin": "https://www.facebook.com",
53
- "connection": "keep-alive",
54
- "Sec-Fetch-Site": "same-origin",
55
- "Sec-Fetch-User": "?1"
56
- };
57
-
58
- let request = require("request").defaults({
59
- jar: true
60
- });
61
-
62
- function setProxy(proxy) {
63
- request = require("request").defaults({
64
- jar: true,
65
- ...(proxy && { proxy })
66
- });
67
- }
68
-
69
- function getHeaders(urlStr, options, ctx, customHeader) {
70
- const headers1 = {
71
- "host": new URL(urlStr).hostname,
72
- ...headers,
73
- "User-Agent": customHeader?.customUserAgent ?? options?.userAgent ?? defaultUserAgent
74
- };
75
- if (ctx && ctx.region) headers1["X-MSGR-Region"] = ctx.region;
76
- if (customHeader) {
77
- Object.assign(headers1, customHeader);
78
- if (customHeader.noRef) delete headers1.referer;
79
- }
80
- return headers1;
81
- }
82
-
83
- function isReadableStream(obj) {
84
- return obj instanceof stream.Stream && typeof obj._read === "function" && getType(obj._readableState) === "Object";
85
- }
86
-
87
- function cleanGet(url) {
88
- return new Promise(function(resolve, reject) {
89
- request.get(url, { timeout: 60000 }, (error, res) => error ? reject(error) : resolve(res));
90
- });
91
- }
92
-
93
- function get(url, jar, qs, options, ctx, customHeader) {
94
- if (getType(qs) === "Object") {
95
- Object.keys(qs).forEach(prop => {
96
- if (getType(qs[prop]) === 'Object') {
97
- qs[prop] = JSON.stringify(qs[prop]);
98
- }
99
- });
100
- }
101
- const op = {
102
- headers: getHeaders(url, options, ctx, customHeader),
103
- timeout: 60000,
104
- qs,
105
- jar,
106
- gzip: true
107
- };
108
- return new Promise(function (resolve, reject) {
109
- request.get(url, op, (error, res) => error ? reject(error) : resolve(res));
110
- });
111
- }
112
-
113
- function post(url, jar, form, options, ctx, customHeader) {
114
- const op = {
115
- headers: getHeaders(url, options, ctx, customHeader),
116
- timeout: 60000,
117
- form,
118
- jar,
119
- gzip: true
120
- };
121
- return new Promise(function (resolve, reject) {
122
- request.post(url, op, (error, res) => error ? reject(error) : resolve(res));
123
- });
124
- }
125
-
126
- function postFormData(url, jar, form, qs, options, ctx) {
127
- if (getType(qs) === "Object") {
128
- Object.keys(qs).forEach(prop => {
129
- if (getType(qs[prop]) === 'Object') {
130
- qs[prop] = JSON.stringify(qs[prop]);
131
- }
132
- });
133
- }
134
- const op = {
135
- headers: getHeaders(url, options, ctx, { 'content-type': 'multipart/form-data' }),
136
- timeout: 60000,
137
- formData: form,
138
- qs,
139
- jar,
140
- gzip: true
141
- };
142
- return new Promise(function (resolve, reject) {
143
- request.post(url, op, (error, res) => error ? reject(error) : resolve(res));
144
- });
145
- }
146
-
147
- function padZeros(val, len = 2) {
148
- return String(val).padStart(len, "0");
149
- }
150
-
151
- function generateThreadingID(clientID) {
152
- const k = Date.now();
153
- const l = Math.floor(Math.random() * 4294967295);
154
- return `<${k}:${l}-${clientID}@mail.projektitan.com>`;
155
- }
156
-
157
- function binaryToDecimal(data) {
158
- let ret = "";
159
- while (data !== "0") {
160
- let end = 0;
161
- let fullName = "";
162
- for (let i = 0; i < data.length; i++) {
163
- end = 2 * end + parseInt(data[i], 10);
164
- if (end >= 10) {
165
- fullName += "1";
166
- end -= 10;
167
- } else {
168
- fullName += "0";
169
- }
170
- }
171
- ret = end.toString() + ret;
172
- const firstOne = fullName.indexOf("1");
173
- data = firstOne === -1 ? "0" : fullName.slice(firstOne);
174
- }
175
- return ret;
176
- }
177
-
178
- function generateOfflineThreadingID() {
179
- const ret = Date.now();
180
- const value = Math.floor(Math.random() * 4294967295);
181
- const str = value.toString(2).padStart(22, "0");
182
- return binaryToDecimal(ret.toString(2) + str);
183
- }
184
-
185
- let h;
186
- const i = {};
187
- const j = {
188
- _: "%", A: "%2", B: "000", C: "%7d", D: "%7b%22", E: "%2c%22", F: "%22%3a", G: "%2c%22ut%22%3a1",
189
- H: "%2c%22bls%22%3a", I: "%2c%22n%22%3a%22%", J: "%22%3a%7b%22i%22%3a0%7d", K: "%2c%22pt%22%3a0%2c%22vis%22%3a",
190
- L: "%2c%22ch%22%3a%7b%22h%22%3a%22", M: "%7b%22v%22%3a2%2c%22time%22%3a1", N: ".channel%22%2c%22sub%22%3a%5b",
191
- O: "%2c%22sb%22%3a1%2c%22t%22%3a%5b", P: "%2c%22ud%22%3a100%2c%22lc%22%3a0", Q: "%5d%2c%22f%22%3anull%2c%22uct%22%3a",
192
- R: ".channel%22%2c%22sub%22%3a%5b1%5d", S: "%22%2c%22m%22%3a0%7d%2c%7b%22i%22%3a", T: "%2c%22blc%22%3a1%2c%22snd%22%3a1%2c%22ct%22%3a",
193
- U: "%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a", V: "%2c%22blc%22%3a0%2c%22snd%22%3a0%2c%22ct%22%3a",
194
- W: "%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a", X: "%2c%22ri%22%3a0%7d%2c%22state%22%3a%7b%22p%22%3a0%2c%22ut%22%3a1",
195
- Y: "%2c%22pt%22%3a0%2c%22vis%22%3a1%2c%22bls%22%3a0%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a",
196
- Z: "%2c%22sb%22%3a1%2c%22t%22%3a%5b%5d%2c%22f%22%3anull%2c%22uct%22%3a0%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a"
197
- };
198
-
199
- (function() {
200
- const l = [];
201
- for (const m in j) {
202
- i[j[m]] = m;
203
- l.push(j[m]);
204
- }
205
- l.reverse();
206
- h = new RegExp(l.join("|"), "g");
207
- })();
208
-
209
- function presenceEncode(str) {
210
- return encodeURIComponent(str)
211
- .replace(/([_A-Z])|%../g, (m, n) => n ? "%" + n.charCodeAt(0).toString(16) : m)
212
- .toLowerCase()
213
- .replace(h, m => i[m]);
214
- }
215
-
216
- function presenceDecode(str) {
217
- return decodeURIComponent(str.replace(/[_A-Z]/g, m => j[m]));
218
- }
219
-
220
- function generatePresence(userID) {
221
- const time = Date.now();
222
- return "E" + presenceEncode(JSON.stringify({
223
- v: 3,
224
- time: Math.floor(time / 1000),
225
- user: userID,
226
- state: {
227
- ut: 0, t2: [], lm2: null, uct2: time, tr: null,
228
- tw: Math.floor(Math.random() * 4294967295) + 1, at: time
229
- },
230
- ch: { ["p_" + userID]: 0 }
231
- }));
232
- }
233
-
234
- function generateAccessiblityCookie() {
235
- const time = Date.now();
236
- return encodeURIComponent(JSON.stringify({ sr: 0, "sr-ts": time, jk: 0, "jk-ts": time, kb: 0, "kb-ts": time, hcm: 0, "hcm-ts": time }));
237
- }
238
-
239
- function getGUID() {
240
- let sectionLength = Date.now();
241
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
242
- const r = Math.floor((sectionLength + Math.random() * 16) % 16);
243
- sectionLength = Math.floor(sectionLength / 16);
244
- return (c === "x" ? r : (r & 7) | 8).toString(16);
245
- });
246
- }
247
-
248
- function getExtension(original_extension, fullFileName = "") {
249
- if (original_extension) return original_extension;
250
- const extension = fullFileName.split(".").pop();
251
- return extension === fullFileName ? "" : extension;
252
- }
253
-
254
- function _formatAttachment(attachment1, attachment2) {
255
- const fullFileName = attachment1.filename;
256
- const fileSize = Number(attachment1.fileSize || 0);
257
- const durationVideo = attachment1.genericMetadata ? Number(attachment1.genericMetadata.videoLength) : undefined;
258
- const durationAudio = attachment1.genericMetadata ? Number(attachment1.genericMetadata.duration) : undefined;
259
- const mimeType = attachment1.mimeType;
260
-
261
- attachment2 = attachment2 || { id: "", image_data: {} };
262
- attachment1 = attachment1.mercury || attachment1;
263
- let blob = attachment1.blob_attachment || attachment1.sticker_attachment;
264
- let type = blob && blob.__typename ? blob.__typename : attachment1.attach_type;
265
-
266
- if (!type && attachment1.sticker_attachment) {
267
- type = "StickerAttachment";
268
- blob = attachment1.sticker_attachment;
269
- } else if (!type && attachment1.extensible_attachment) {
270
- if (attachment1.extensible_attachment.story_attachment?.target?.__typename === "MessageLocation") {
271
- type = "MessageLocation";
272
- } else {
273
- type = "ExtensibleAttachment";
274
- }
275
- blob = attachment1.extensible_attachment;
276
- }
277
-
278
- switch (type) {
279
- case "sticker":
280
- return {
281
- type: "sticker", ID: attachment1.metadata.stickerID.toString(), url: attachment1.url,
282
- packID: attachment1.metadata.packID.toString(), spriteUrl: attachment1.metadata.spriteURI,
283
- spriteUrl2x: attachment1.metadata.spriteURI2x, width: attachment1.metadata.width, height: attachment1.metadata.height,
284
- caption: attachment2.caption, description: attachment2.description, frameCount: attachment1.metadata.frameCount,
285
- frameRate: attachment1.metadata.frameRate, framesPerRow: attachment1.metadata.framesPerRow, framesPerCol: attachment1.metadata.framesPerCol,
286
- stickerID: attachment1.metadata.stickerID.toString(), spriteURI: attachment1.metadata.spriteURI, spriteURI2x: attachment1.metadata.spriteURI2x
287
- };
288
- case "file":
289
- return {
290
- type: "file", ID: attachment2.id.toString(), fullFileName: fullFileName, filename: attachment1.name,
291
- fileSize: fileSize, original_extension: getExtension(attachment1.original_extension, fullFileName),
292
- mimeType: mimeType, url: attachment1.url, isMalicious: attachment2.is_malicious, contentType: attachment2.mime_type, name: attachment1.name
293
- };
294
- case "photo":
295
- return {
296
- type: "photo", ID: attachment1.metadata.fbid.toString(), filename: attachment1.fileName, fullFileName: fullFileName,
297
- fileSize: fileSize, original_extension: getExtension(attachment1.original_extension, fullFileName), mimeType: mimeType,
298
- thumbnailUrl: attachment1.thumbnail_url, previewUrl: attachment1.preview_url, previewWidth: attachment1.preview_width,
299
- previewHeight: attachment1.preview_height, largePreviewUrl: attachment1.large_preview_url, largePreviewWidth: attachment1.large_preview_width,
300
- largePreviewHeight: attachment1.large_preview_height, url: attachment1.metadata.url, width: attachment1.metadata.dimensions.split(",")[0],
301
- height: attachment1.metadata.dimensions.split(",")[1], name: fullFileName
302
- };
303
- case "animated_image":
304
- return {
305
- type: "animated_image", ID: attachment2.id.toString(), filename: attachment2.filename, fullFileName: fullFileName,
306
- original_extension: getExtension(attachment2.original_extension, fullFileName), mimeType: mimeType, previewUrl: attachment1.preview_url,
307
- previewWidth: attachment1.preview_width, previewHeight: attachment1.preview_height, url: attachment2.image_data.url,
308
- width: attachment2.image_data.width, height: attachment2.image_data.height, name: attachment1.name, facebookUrl: attachment1.url,
309
- thumbnailUrl: attachment1.thumbnail_url, rawGifImage: attachment2.image_data.raw_gif_image, rawWebpImage: attachment2.image_data.raw_webp_image,
310
- animatedGifUrl: attachment2.image_data.animated_gif_url, animatedGifPreviewUrl: attachment2.image_data.animated_gif_preview_url,
311
- animatedWebpUrl: attachment2.image_data.animated_webp_url, animatedWebpPreviewUrl: attachment2.image_data.animated_webp_preview_url
312
- };
313
- case "share":
314
- return {
315
- type: "share", ID: attachment1.share.share_id.toString(), url: attachment2.href, title: attachment1.share.title,
316
- description: attachment1.share.description, source: attachment1.share.source, image: attachment1.share.media.image,
317
- width: attachment1.share.media.image_size.width, height: attachment1.share.media.image_size.height, playable: attachment1.share.media.playable,
318
- duration: attachment1.share.media.duration, subattachments: attachment1.share.subattachments, properties: {},
319
- animatedImageSize: attachment1.share.media.animated_image_size, facebookUrl: attachment1.share.uri, target: attachment1.share.target, styleList: attachment1.share.style_list
320
- };
321
- case "video":
322
- return {
323
- type: "video", ID: attachment1.metadata.fbid.toString(), filename: attachment1.name, fullFileName: fullFileName,
324
- original_extension: getExtension(attachment1.original_extension, fullFileName), mimeType: mimeType, duration: durationVideo,
325
- previewUrl: attachment1.preview_url, previewWidth: attachment1.preview_width, previewHeight: attachment1.preview_height,
326
- url: attachment1.url, width: attachment1.metadata.dimensions.width, height: attachment1.metadata.dimensions.height,
327
- videoType: "unknown", thumbnailUrl: attachment1.thumbnail_url
328
- };
329
- case "error":
330
- return { type: "error", attachment1: attachment1, attachment2: attachment2 };
331
- case "MessageImage":
332
- return {
333
- type: "photo", ID: blob.legacy_attachment_id, filename: blob.filename, fullFileName: fullFileName, fileSize: fileSize,
334
- original_extension: getExtension(blob.original_extension, fullFileName), mimeType: mimeType, thumbnailUrl: blob.thumbnail.uri,
335
- previewUrl: blob.preview.uri, previewWidth: blob.preview.width, previewHeight: blob.preview.height, largePreviewUrl: blob.large_preview.uri,
336
- largePreviewWidth: blob.large_preview.width, largePreviewHeight: blob.large_preview.height, url: blob.large_preview.uri,
337
- width: blob.original_dimensions.x, height: blob.original_dimensions.y, name: blob.filename
338
- };
339
- case "MessageAnimatedImage":
340
- return {
341
- type: "animated_image", ID: blob.legacy_attachment_id, filename: blob.filename, fullFileName: fullFileName,
342
- original_extension: getExtension(blob.original_extension, fullFileName), mimeType: mimeType, previewUrl: blob.preview_image.uri,
343
- previewWidth: blob.preview_image.width, previewHeight: blob.preview_image.height, url: blob.animated_image.uri,
344
- width: blob.animated_image.width, height: blob.animated_image.height, thumbnailUrl: blob.preview_image.uri, name: blob.filename,
345
- facebookUrl: blob.animated_image.uri, rawGifImage: blob.animated_image.uri, animatedGifUrl: blob.animated_image.uri,
346
- animatedGifPreviewUrl: blob.preview_image.uri, animatedWebpUrl: blob.animated_image.uri, animatedWebpPreviewUrl: blob.preview_image.uri
347
- };
348
- case "MessageVideo":
349
- return {
350
- type: "video", ID: blob.legacy_attachment_id, filename: blob.filename, fullFileName: fullFileName,
351
- original_extension: getExtension(blob.original_extension, fullFileName), fileSize: fileSize, duration: durationVideo,
352
- mimeType: mimeType, previewUrl: blob.large_image.uri, previewWidth: blob.large_image.width, previewHeight: blob.large_image.height,
353
- url: blob.playable_url, width: blob.original_dimensions.x, height: blob.original_dimensions.y, videoType: blob.video_type.toLowerCase(),
354
- thumbnailUrl: blob.large_image.uri
355
- };
356
- case "MessageAudio":
357
- return {
358
- type: "audio", ID: blob.url_shimhash, filename: blob.filename, fullFileName: fullFileName, fileSize: fileSize,
359
- duration: durationAudio, original_extension: getExtension(blob.original_extension, fullFileName), mimeType: mimeType,
360
- audioType: blob.audio_type, url: blob.playable_url, isVoiceMail: blob.is_voicemail
361
- };
362
- case "StickerAttachment":
363
- case "Sticker":
364
- return {
365
- type: "sticker", ID: blob.id, url: blob.url, packID: blob.pack ? blob.pack.id : null, spriteUrl: blob.sprite_image,
366
- spriteUrl2x: blob.sprite_image_2x, width: blob.width, height: blob.height, caption: blob.label, description: blob.label,
367
- frameCount: blob.frame_count, frameRate: blob.frame_rate, framesPerRow: blob.frames_per_row, framesPerCol: blob.frames_per_column,
368
- stickerID: blob.id, spriteURI: blob.sprite_image, spriteURI2x: blob.sprite_image_2x
369
- };
370
- case "MessageLocation":
371
- try {
372
- const urlAttach = blob.story_attachment.url;
373
- const mediaAttach = blob.story_attachment.media;
374
- const u = querystring.parse(url.parse(urlAttach).query).u;
375
- const where1 = querystring.parse(url.parse(u).query).where1;
376
- const address = where1.split(", ");
377
- let latitude = Number.parseFloat(address[0]);
378
- let longitude = Number.parseFloat(address[1]);
379
- let imageUrl, width, height;
380
- if (mediaAttach?.image) {
381
- imageUrl = mediaAttach.image.uri;
382
- width = mediaAttach.image.width;
383
- height = mediaAttach.image.height;
384
- }
385
- return {
386
- type: "location", ID: blob.legacy_attachment_id, latitude, longitude, image: imageUrl, width, height,
387
- url: u || urlAttach, address: where1, facebookUrl: blob.story_attachment.url, target: blob.story_attachment.target,
388
- styleList: blob.story_attachment.style_list
389
- };
390
- } catch (err) {
391
- return { type: "error", error: "Failed to parse location", detail: err };
392
- }
393
- case "ExtensibleAttachment":
394
- return {
395
- type: "share", ID: blob.legacy_attachment_id, url: blob.story_attachment.url, title: blob.story_attachment.title_with_entities.text,
396
- description: blob.story_attachment.description?.text, source: blob.story_attachment.source?.text || null,
397
- image: blob.story_attachment.media?.image?.uri, width: blob.story_attachment.media?.image?.width, height: blob.story_attachment.media?.image?.height,
398
- playable: blob.story_attachment.media?.is_playable, duration: blob.story_attachment.media?.playable_duration_in_ms,
399
- playableUrl: blob.story_attachment.media?.playable_url || null, subattachments: blob.story_attachment.subattachments,
400
- properties: (blob.story_attachment.properties || []).reduce(function(obj, cur) {
401
- obj[cur.key] = cur.value.text;
402
- return obj;
403
- }, {}),
404
- facebookUrl: blob.story_attachment.url, target: blob.story_attachment.target, styleList: blob.story_attachment.style_list
405
- };
406
- case "MessageFile":
407
- return {
408
- type: "file", ID: blob.message_file_fbid, fullFileName: fullFileName, filename: blob.filename, fileSize: fileSize,
409
- mimeType: blob.mimetype, original_extension: blob.original_extension || fullFileName.split(".").pop(), url: blob.url,
410
- isMalicious: blob.is_malicious, contentType: blob.content_type, name: blob.filename
411
- };
412
- default:
413
- throw new Error("unrecognized attach_file of type " + type + "`" + JSON.stringify(attachment1, null, 4) + " attachment2: " + JSON.stringify(attachment2, null, 4) + "`");
414
- }
415
- }
416
-
417
- function formatAttachment(attachments, attachmentIds, attachmentMap, shareMap) {
418
- const mapToUse = shareMap || attachmentMap;
419
- return attachments ? attachments.map(function(val, i) {
420
- if (!mapToUse || !attachmentIds || !mapToUse[attachmentIds[i]]) {
421
- return _formatAttachment(val);
422
- }
423
- return _formatAttachment(val, mapToUse[attachmentIds[i]]);
424
- }) : [];
425
- }
426
-
427
- function formatDeltaMessage(m) {
428
- const md = m.delta.messageMetadata;
429
- const mdata = m.delta.data?.prng ? JSON.parse(m.delta.data.prng) : [];
430
- const mentions = {};
431
-
432
- for (let i = 0; i < mdata.length; i++) {
433
- if (mdata[i].i && mdata[i].o !== undefined && mdata[i].l) {
434
- mentions[mdata[i].i] = m.delta.body.substring(mdata[i].o, mdata[i].o + mdata[i].l);
435
- }
436
- }
437
-
438
- return {
439
- type: "message",
440
- senderID: formatID(md.actorFbId.toString()),
441
- body: m.delta.body || "",
442
- threadID: formatID((md.threadKey.threadFbId || md.threadKey.otherUserFbId).toString()),
443
- messageID: md.messageId,
444
- attachments: (m.delta.attachments || []).map(v => _formatAttachment(v)),
445
- mentions: mentions,
446
- timestamp: md.timestamp,
447
- isGroup: !!md.threadKey.threadFbId,
448
- participantIDs: m.delta.participants
449
- };
450
- }
451
-
452
- function formatID(id) {
453
- return (id != null) ? id.replace(/(fb)?id[:.]/, "") : id;
454
- }
455
-
456
- function formatMessage(m) {
457
- const originalMessage = m.message ? m.message : m;
458
- const obj = {
459
- type: "message",
460
- senderName: originalMessage.sender_name,
461
- senderID: formatID(originalMessage.sender_fbid.toString()),
462
- participantNames: originalMessage.group_thread_info ? originalMessage.group_thread_info.participant_names : [originalMessage.sender_name.split(" ")[0]],
463
- participantIDs: originalMessage.group_thread_info ? originalMessage.group_thread_info.participant_ids.map(v => formatID(v.toString())) : [formatID(originalMessage.sender_fbid)],
464
- body: originalMessage.body || "",
465
- threadID: formatID((originalMessage.thread_fbid || originalMessage.other_user_fbid).toString()),
466
- threadName: originalMessage.group_thread_info ? originalMessage.group_thread_info.name : originalMessage.sender_name,
467
- location: originalMessage.coordinates ? originalMessage.coordinates : null,
468
- messageID: originalMessage.mid ? originalMessage.mid.toString() : originalMessage.message_id,
469
- attachments: formatAttachment(originalMessage.attachments, originalMessage.attachmentIds, originalMessage.attachment_map, originalMessage.share_map),
470
- timestamp: originalMessage.timestamp,
471
- timestampAbsolute: originalMessage.timestamp_absolute,
472
- timestampRelative: originalMessage.timestamp_relative,
473
- timestampDatetime: originalMessage.timestamp_datetime,
474
- tags: originalMessage.tags,
475
- reactions: originalMessage.reactions ? originalMessage.reactions : [],
476
- isUnread: originalMessage.is_unread
477
- };
478
-
479
- if (m.type === "pages_messaging") obj.pageID = m.realtime_viewer_fbid.toString();
480
- obj.isGroup = obj.participantIDs.length > 2;
481
- return obj;
482
- }
483
-
484
- function formatEvent(m) {
485
- const originalMessage = m.message ? m.message : m;
486
- let logMessageType = originalMessage.log_message_type;
487
- let logMessageData;
488
- if (logMessageType === "log:generic-admin-text") {
489
- logMessageData = originalMessage.log_message_data.untypedData;
490
- logMessageType = getAdminTextMessageType(originalMessage.log_message_data.message_type);
491
- } else {
492
- logMessageData = originalMessage.log_message_data;
493
- }
494
-
495
- return Object.assign(formatMessage(originalMessage), {
496
- type: "event",
497
- logMessageType: logMessageType,
498
- logMessageData: logMessageData,
499
- logMessageBody: originalMessage.log_message_body
500
- });
501
- }
502
-
503
- function formatHistoryMessage(m) {
504
- return m.action_type === "ma-type:log-message" ? formatEvent(m) : formatMessage(m);
505
- }
506
-
507
- function getAdminTextMessageType(type) {
508
- switch (type) {
509
- case 'unpin_messages_v2': return 'log:unpin-message';
510
- case 'pin_messages_v2': return 'log:pin-message';
511
- case "change_thread_theme": return "log:thread-color";
512
- case "change_thread_icon":
513
- case 'change_thread_quick_reaction': return "log:thread-icon";
514
- case "change_thread_nickname": return "log:user-nickname";
515
- case "change_thread_admins": return "log:thread-admins";
516
- case "group_poll": return "log:thread-poll";
517
- case "change_thread_approval_mode": return "log:thread-approval-mode";
518
- case "messenger_call_log":
519
- case "participant_joined_group_call": return "log:thread-call";
520
- default: return type;
521
- }
522
- }
523
-
524
- function formatDeltaEvent(m) {
525
- let logMessageType;
526
- let logMessageData;
527
-
528
- switch (m.class) {
529
- case "AdminTextMessage":
530
- logMessageData = m.untypedData;
531
- logMessageType = getAdminTextMessageType(m.type);
532
- break;
533
- case "ThreadName":
534
- logMessageType = "log:thread-name";
535
- logMessageData = { name: m.name };
536
- break;
537
- case "ParticipantsAddedToGroupThread":
538
- logMessageType = "log:subscribe";
539
- logMessageData = { addedParticipants: m.addedParticipants };
540
- break;
541
- case "ParticipantLeftGroupThread":
542
- logMessageType = "log:unsubscribe";
543
- logMessageData = { leftParticipantFbId: m.leftParticipantFbId };
544
- break;
545
- case "ApprovalQueue":
546
- logMessageType = "log:approval-queue";
547
- logMessageData = {
548
- approvalQueue: {
549
- action: m.action,
550
- recipientFbId: m.recipientFbId,
551
- requestSource: m.requestSource,
552
- ...m.messageMetadata
553
- }
554
- };
555
- break;
556
- }
557
- return {
558
- type: "event",
559
- threadID: formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),
560
- messageID: m.messageMetadata.messageId.toString(),
561
- logMessageType,
562
- logMessageData,
563
- logMessageBody: m.messageMetadata.adminText,
564
- timestamp: m.messageMetadata.timestamp,
565
- author: m.messageMetadata.actorFbId,
566
- participantIDs: m.participants
567
- };
568
- }
569
-
570
- function formatTyp(event) {
571
- return {
572
- isTyping: !!event.st,
573
- from: event.from.toString(),
574
- threadID: formatID((event.to || event.thread_fbid || event.from).toString()),
575
- fromMobile: event.hasOwnProperty("from_mobile") ? event.from_mobile : true,
576
- userID: (event.realtime_viewer_fbid || event.from).toString(),
577
- type: "typ"
578
- };
579
- }
580
-
581
- function formatDeltaReadReceipt(delta) {
582
- return {
583
- reader: (delta.threadKey.otherUserFbId || delta.actorFbId).toString(),
584
- time: delta.actionTimestampMs,
585
- threadID: formatID((delta.threadKey.otherUserFbId || delta.threadKey.threadFbId).toString()),
586
- type: "read_receipt"
587
- };
588
- }
589
-
590
- function formatReadReceipt(event) {
591
- return {
592
- reader: event.reader.toString(),
593
- time: event.time,
594
- threadID: formatID((event.thread_fbid || event.reader).toString()),
595
- type: "read_receipt"
596
- };
597
- }
598
-
599
- function formatRead(event) {
600
- return {
601
- threadID: formatID(((event.chat_ids && event.chat_ids[0]) || (event.thread_fbids && event.thread_fbids[0])).toString()),
602
- time: event.timestamp,
603
- type: "read"
604
- };
605
- }
606
-
607
- function getFrom(str, startToken, endToken) {
608
- const start = str.indexOf(startToken) + startToken.length;
609
- if (start < startToken.length) return "";
610
- const lastHalf = str.substring(start);
611
- const end = lastHalf.indexOf(endToken);
612
- if (end === -1) {
613
- throw Error("Could not find endTime `" + endToken + "` in the given string.");
614
- }
615
- return lastHalf.substring(0, end);
616
- }
617
-
618
- function makeParsable(html) {
619
- const withoutForLoop = html.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, "");
620
- const maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
621
- if (maybeMultipleObjects.length === 1) return maybeMultipleObjects;
622
- return "[" + maybeMultipleObjects.join("},{") + "]";
623
- }
624
-
625
- function arrToForm(form) {
626
- return arrayToObject(form, v => v.name, v => v.val);
627
- }
628
-
629
- function arrayToObject(arr, getKey, getValue) {
630
- return arr.reduce(function(acc, val) {
631
- acc[getKey(val)] = getValue(val);
632
- return acc;
633
- }, {});
634
- }
635
-
636
- function getSignatureID() {
637
- return Math.floor(Math.random() * 2147483648).toString(16);
638
- }
639
-
640
- function generateTimestampRelative() {
641
- const d = new Date();
642
- return d.getHours() + ":" + padZeros(d.getMinutes());
643
- }
644
-
645
- function makeDefaults(html, userID, ctx) {
646
- let reqCounter = 1;
647
- const revision = getFrom(html, 'revision":', ",");
648
- function mergeWithDefaults(obj) {
649
- const newObj = {
650
- av: userID,
651
- __user: userID,
652
- __req: (reqCounter++).toString(36),
653
- __rev: revision,
654
- __a: 1,
655
- ...(ctx && {
656
- fb_dtsg: ctx.fb_dtsg,
657
- jazoest: ctx.jazoest
658
- })
659
- };
660
-
661
- if (!obj) return newObj;
662
-
663
- Object.keys(obj).forEach(prop => {
664
- if (obj.hasOwnProperty(prop) && !newObj.hasOwnProperty(prop)) {
665
- newObj[prop] = obj[prop];
666
- }
667
- });
668
- return newObj;
669
- }
670
-
671
- return {
672
- get: (url, jar, qs, ctxx, customHeader = {}) => get(url, jar, mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx, customHeader),
673
- post: (url, jar, form, ctxx, customHeader = {}) => post(url, jar, mergeWithDefaults(form), ctx.globalOptions, ctxx || ctx, customHeader),
674
- postFormData: (url, jar, form, qs, ctxx) => postFormData(url, jar, mergeWithDefaults(form), mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx)
675
- };
676
- }
677
-
678
- function parseAndCheckLogin(ctx, http, retryCount = 0) {
679
- const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
680
- const _try = (tryData) => new Promise(function(resolve, reject) {
681
- try {
682
- resolve(tryData());
683
- } catch (error) {
684
- reject(error);
685
- }
686
- });
687
-
688
- return function(data) {
689
- function any() {
690
- if (data.statusCode >= 500 && data.statusCode < 600) {
691
- if (retryCount >= 5) {
692
- const err = new Error("Request retry failed. Check the `res` and `statusCode` property on this error.");
693
- err.statusCode = data.statusCode;
694
- err.res = data.body;
695
- err.error = "Request retry failed. Check the `res` and `statusCode` property on this error.";
696
- throw err;
697
- }
698
- retryCount++;
699
- const retryTime = Math.floor(Math.random() * 5000);
700
- console.warn("parseAndCheckLogin", "Got status code " + data.statusCode + " - " + retryCount + ". attempt to retry in " + retryTime + " milliseconds...");
701
- const url = data.request.uri.protocol + "//" + data.request.uri.hostname + data.request.uri.pathname;
702
-
703
- const contentType = data.request.headers?.["content-type"] || "";
704
- if (contentType.split(";")[0] === "multipart/form-data") {
705
- return delay(retryTime)
706
- .then(() => http.postFormData(url, ctx.jar, data.request.formData))
707
- .then(parseAndCheckLogin(ctx, http, retryCount));
708
- } else {
709
- return delay(retryTime)
710
- .then(() => http.post(url, ctx.jar, data.request.formData))
711
- .then(parseAndCheckLogin(ctx, http, retryCount));
712
- }
713
- }
714
-
715
- if (data.statusCode === 404) return;
716
- if (data.statusCode !== 200)
717
- throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
718
-
719
- let res = null;
720
- try {
721
- res = JSON.parse(makeParsable(data.body));
722
- } catch (e) {
723
- const err = new Error("JSON.parse error. Check the `detail` property on this error.");
724
- err.error = "JSON.parse error. Check the `detail` property on this error.";
725
- err.detail = e;
726
- err.res = data.body;
727
- throw err;
728
- }
729
-
730
- if (res.redirect && data.request.method === "GET") {
731
- return http.get(res.redirect, ctx.jar).then(parseAndCheckLogin(ctx, http));
732
- }
733
-
734
- if (res.jsmods?.require && Array.isArray(res.jsmods.require[0]) && res.jsmods.require[0][0] === "Cookie") {
735
- res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
736
- const requireCookie = res.jsmods.require[0][3];
737
- ctx.jar.setCookie(formatCookie(requireCookie, "facebook"), "https://www.facebook.com");
738
- ctx.jar.setCookie(formatCookie(requireCookie, "messenger"), "https://www.messenger.com");
739
- }
740
-
741
- if (res.jsmods && Array.isArray(res.jsmods.require)) {
742
- const arr = res.jsmods.require;
743
- for (const i in arr) {
744
- if (arr[i][0] === "DTSG" && arr[i][1] === "setToken") {
745
- ctx.fb_dtsg = arr[i][3][0];
746
- ctx.ttstamp = "2";
747
- for (let j = 0; j < ctx.fb_dtsg.length; j++) {
748
- ctx.ttstamp += ctx.fb_dtsg.charCodeAt(j);
749
- }
750
- }
751
- }
752
- }
753
-
754
- if (res.error === 1357001) {
755
- const err = new Error('Facebook blocked the login');
756
- err.error = "Not logged in.";
757
- throw err;
758
- }
759
- return res;
760
- }
761
- return _try(any);
762
- };
763
- }
764
-
765
- function saveCookies(jar) {
766
- return function(res) {
767
- const cookies = res.headers?.["set-cookie"] || [];
768
- cookies.forEach(function(c) {
769
- if (c.indexOf(".facebook.com") > -1) {
770
- jar.setCookie(c, "https://www.facebook.com");
771
- }
772
- const c2 = c.replace(/domain=\.facebook\.com/, "domain=.messenger.com");
773
- jar.setCookie(c2, "https://www.messenger.com");
774
- });
775
- return res;
776
- };
777
- }
778
-
779
- const NUM_TO_MONTH = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
780
- const NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
781
-
782
- function formatDate(date) {
783
- const d = padZeros(date.getUTCDate());
784
- const h = padZeros(date.getUTCHours());
785
- const m = padZeros(date.getUTCMinutes());
786
- const s = padZeros(date.getUTCSeconds());
787
- return `${NUM_TO_DAY[date.getUTCDay()]}, ${d} ${NUM_TO_MONTH[date.getUTCMonth()]} ${date.getUTCFullYear()} ${h}:${m}:${s} GMT`;
788
- }
789
-
790
- function formatCookie(arr, urlStr) {
791
- return arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + urlStr + ".com";
792
- }
793
-
794
- function formatThread(data) {
795
- return {
796
- threadID: formatID(data.thread_fbid.toString()),
797
- participants: data.participants.map(formatID),
798
- participantIDs: data.participants.map(formatID),
799
- name: data.name,
800
- nicknames: data.custom_nickname,
801
- snippet: data.snippet,
802
- snippetAttachments: data.snippet_attachments,
803
- snippetSender: formatID((data.snippet_sender || "").toString()),
804
- unreadCount: data.unread_count,
805
- messageCount: data.message_count,
806
- imageSrc: data.image_src,
807
- timestamp: data.timestamp,
808
- serverTimestamp: data.server_timestamp,
809
- muteUntil: data.mute_until,
810
- isCanonicalUser: data.is_canonical_user,
811
- isCanonical: data.is_canonical,
812
- isSubscribed: data.is_subscribed,
813
- folder: data.folder,
814
- isArchived: data.is_archived,
815
- recipientsLoadable: data.recipients_loadable,
816
- hasEmailParticipant: data.has_email_participant,
817
- readOnly: data.read_only,
818
- canReply: data.can_reply,
819
- cannotReplyReason: data.cannot_reply_reason,
820
- lastMessageTimestamp: data.last_message_timestamp,
821
- lastReadTimestamp: data.last_read_timestamp,
822
- lastMessageType: data.last_message_type,
823
- emoji: data.custom_like_icon,
824
- color: data.custom_color,
825
- adminIDs: data.admin_ids,
826
- threadType: data.thread_type
827
- };
828
- }
829
-
830
- function formatProxyPresence(presence, userID) {
831
- if (presence.lat === undefined || presence.p === undefined) return null;
832
- return { type: "presence", timestamp: presence.lat * 1000, userID: userID, statuses: presence.p };
833
- }
834
-
835
- function formatPresence(presence, userID) {
836
- return { type: "presence", timestamp: presence.la * 1000, userID: userID, statuses: presence.a };
837
- }
838
-
839
- function decodeClientPayload(payload) {
840
- try {
841
- return JSON.parse(Buffer.from(payload).toString('utf8'));
842
- } catch (e) {
843
- return JSON.parse(String.fromCharCode.apply(null, payload));
844
- }
845
- }
846
-
847
- function getAppState(jar) {
848
- return jar.getCookies("https://www.facebook.com").concat(jar.getCookies("https://www.messenger.com"));
849
- }
850
-
851
- function getAccessFromBusiness(jar, Options) {
852
- return function(res) {
853
- const html = res ? res.body : null;
854
- return get('https://business.facebook.com/content_management', jar, null, Options, null, { noRef: true })
855
- .then(function(resData) {
856
- const match = /"accessToken":"([^.]+)","clientID":/g.exec(resData.body);
857
- const token = match ? match[1] : null;
858
- return [html, token];
859
- })
860
- .catch(function() {
861
- return [html, null];
862
- });
863
- };
864
- }
865
-
866
- const meta = prop => new RegExp(`<meta property="${prop}" content="([^"]*)"`);
867
-
868
- module.exports = {
869
- log(...args) { console.log(ws, chalk.green.bold("[LOG]"), ...args); },
870
- error(...args) { console.error(ws, chalk.red.bold("[ERROR]"), ...args); },
871
- warn(...args) { console.warn(ws, chalk.yellow.bold("[WARNING]"), ...args); },
872
- isReadableStream,
873
- cleanGet,
874
- get,
875
- post,
876
- postFormData,
877
- generateThreadingID,
878
- generateOfflineThreadingID,
879
- getGUID,
880
- getFrom,
881
- makeParsable,
882
- arrToForm,
883
- getSignatureID,
884
- getJar: request.jar,
885
- generateTimestampRelative,
886
- makeDefaults,
887
- parseAndCheckLogin,
888
- saveCookies,
889
- getType,
890
- _formatAttachment,
891
- formatHistoryMessage,
892
- formatID,
893
- formatMessage,
894
- formatDeltaEvent,
895
- formatDeltaMessage,
896
- formatProxyPresence,
897
- formatPresence,
898
- formatTyp,
899
- formatDeltaReadReceipt,
900
- formatCookie,
901
- formatThread,
902
- formatReadReceipt,
903
- formatRead,
904
- generatePresence,
905
- generateAccessiblityCookie,
906
- formatDate,
907
- decodeClientPayload,
908
- getAppState,
909
- getAdminTextMessageType,
910
- setProxy,
911
- getAccessFromBusiness,
912
- presenceDecode,
913
- presenceEncode,
914
- headers,
915
- defaultUserAgent,
916
- windowsUserAgent,
917
- randomUserAgent,
918
- meta
919
- };