@dongdev/fca-unofficial 1.0.19 → 2.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 (128) hide show
  1. package/.gitattributes +1 -0
  2. package/CHANGELOG.md +30 -27
  3. package/DOCS.md +727 -592
  4. package/README.md +94 -97
  5. package/func/logger.js +112 -0
  6. package/html.html +474 -0
  7. package/index.js +1 -379
  8. package/module/config.js +26 -0
  9. package/module/login.js +45 -0
  10. package/module/loginHelper.js +634 -0
  11. package/module/options.js +49 -0
  12. package/package.json +6 -39
  13. package/src/api/action/addExternalModule.js +25 -0
  14. package/src/api/action/changeAvatar.js +136 -0
  15. package/src/api/action/changeBio.js +76 -0
  16. package/src/api/action/getCurrentUserID.js +7 -0
  17. package/src/api/action/handleFriendRequest.js +57 -0
  18. package/src/api/action/logout.js +75 -0
  19. package/src/{refreshFb_dtsg.js → api/action/refreshFb_dtsg.js} +8 -8
  20. package/src/api/action/setPostReaction.js +107 -0
  21. package/src/api/action/unfriend.js +55 -0
  22. package/src/api/http/httpGet.js +65 -0
  23. package/src/api/http/httpPost.js +65 -0
  24. package/src/{postFormData.js → api/http/postFormData.js} +10 -10
  25. package/src/api/messaging/addUserToGroup.js +69 -0
  26. package/src/api/messaging/changeAdminStatus.js +103 -0
  27. package/src/api/messaging/changeArchivedStatus.js +55 -0
  28. package/src/api/messaging/changeBlockedStatus.js +49 -0
  29. package/src/api/messaging/changeGroupImage.js +135 -0
  30. package/src/api/messaging/changeNickname.js +59 -0
  31. package/src/api/messaging/changeThreadColor.js +65 -0
  32. package/src/api/messaging/createNewGroup.js +88 -0
  33. package/src/api/messaging/createPoll.js +70 -0
  34. package/src/api/messaging/deleteMessage.js +56 -0
  35. package/src/api/messaging/deleteThread.js +56 -0
  36. package/src/api/messaging/forwardAttachment.js +60 -0
  37. package/src/api/messaging/getEmojiUrl.js +29 -0
  38. package/src/api/messaging/getFriendsList.js +83 -0
  39. package/src/api/messaging/getMessage.js +834 -0
  40. package/src/api/messaging/getThreadHistory.js +681 -0
  41. package/src/api/messaging/handleMessageRequest.js +65 -0
  42. package/src/api/messaging/markAsDelivered.js +57 -0
  43. package/src/api/messaging/markAsRead.js +88 -0
  44. package/src/api/messaging/markAsReadAll.js +50 -0
  45. package/src/api/messaging/markAsSeen.js +61 -0
  46. package/src/api/messaging/muteThread.js +51 -0
  47. package/src/api/messaging/removeUserFromGroup.js +79 -0
  48. package/src/api/messaging/resolvePhotoUrl.js +44 -0
  49. package/src/api/messaging/searchForThread.js +53 -0
  50. package/src/api/messaging/sendMessage.js +306 -0
  51. package/src/api/messaging/sendMessageMqtt.js +321 -0
  52. package/src/api/messaging/sendTypingIndicator.js +110 -0
  53. package/src/{setMessageReaction.js → api/messaging/setMessageReaction.js} +20 -20
  54. package/src/api/messaging/setTitle.js +90 -0
  55. package/src/api/messaging/shareContact.js +51 -0
  56. package/src/api/messaging/threadColors.js +131 -0
  57. package/src/api/messaging/unsendMessage.js +44 -0
  58. package/src/api/messaging/uploadAttachment.js +93 -0
  59. package/src/api/socket/detail/buildStream.js +100 -0
  60. package/src/{listenMqtt.js → api/socket/listenMqtt.js} +172 -256
  61. package/src/api/threads/changeThreadEmoji.js +55 -0
  62. package/src/api/threads/getThreadInfo.js +572 -0
  63. package/src/{getThreadList.js → api/threads/getThreadList.js} +110 -54
  64. package/src/api/threads/getThreadPictures.js +79 -0
  65. package/src/api/users/getUserID.js +66 -0
  66. package/src/api/users/getUserInfo.js +88 -0
  67. package/src/core/sendReqMqtt.js +63 -0
  68. package/{lib → src}/database/models/index.js +12 -10
  69. package/{lib → src}/database/models/thread.js +5 -5
  70. package/{lib → src}/database/threadData.js +19 -14
  71. package/src/utils/client.js +159 -0
  72. package/src/utils/constants.js +13 -0
  73. package/src/utils/format.js +60 -0
  74. package/src/utils/headers.js +41 -0
  75. package/src/utils/index.js +1497 -0
  76. package/src/utils/request.js +147 -0
  77. package/lib/logger.js +0 -96
  78. package/src/addExternalModule.js +0 -19
  79. package/src/addUserToGroup.js +0 -113
  80. package/src/changeAdminStatus.js +0 -79
  81. package/src/changeArchivedStatus.js +0 -55
  82. package/src/changeAvatar.js +0 -126
  83. package/src/changeBio.js +0 -77
  84. package/src/changeBlockedStatus.js +0 -47
  85. package/src/changeGroupImage.js +0 -132
  86. package/src/changeNickname.js +0 -59
  87. package/src/changeThreadColor.js +0 -65
  88. package/src/changeThreadEmoji.js +0 -55
  89. package/src/createNewGroup.js +0 -86
  90. package/src/createPoll.js +0 -71
  91. package/src/deleteMessage.js +0 -56
  92. package/src/deleteThread.js +0 -56
  93. package/src/forwardAttachment.js +0 -60
  94. package/src/getCurrentUserID.js +0 -7
  95. package/src/getEmojiUrl.js +0 -29
  96. package/src/getFriendsList.js +0 -83
  97. package/src/getMessage.js +0 -796
  98. package/src/getThreadHistory.js +0 -666
  99. package/src/getThreadInfo.js +0 -535
  100. package/src/getThreadPictures.js +0 -79
  101. package/src/getUserID.js +0 -66
  102. package/src/getUserInfo.js +0 -80
  103. package/src/handleFriendRequest.js +0 -61
  104. package/src/handleMessageRequest.js +0 -65
  105. package/src/httpGet.js +0 -57
  106. package/src/httpPost.js +0 -57
  107. package/src/httpPostFormData.js +0 -63
  108. package/src/logout.js +0 -75
  109. package/src/markAsDelivered.js +0 -58
  110. package/src/markAsRead.js +0 -80
  111. package/src/markAsReadAll.js +0 -50
  112. package/src/markAsSeen.js +0 -59
  113. package/src/muteThread.js +0 -52
  114. package/src/removeUserFromGroup.js +0 -79
  115. package/src/resolvePhotoUrl.js +0 -45
  116. package/src/searchForThread.js +0 -53
  117. package/src/sendMessage.js +0 -328
  118. package/src/sendMessageMqtt.js +0 -316
  119. package/src/sendTypingIndicator.js +0 -103
  120. package/src/setPostReaction.js +0 -109
  121. package/src/setTitle.js +0 -86
  122. package/src/shareContact.js +0 -49
  123. package/src/threadColors.js +0 -131
  124. package/src/unfriend.js +0 -52
  125. package/src/unsendMessage.js +0 -49
  126. package/src/uploadAttachment.js +0 -95
  127. package/utils.js +0 -1387
  128. /package/{lib → func}/login.js +0 -0
package/utils.js DELETED
@@ -1,1387 +0,0 @@
1
- "use strict";
2
- var url = require("url");
3
- const log = require("npmlog");
4
- const stream = require("stream");
5
- const bluebird = require("bluebird");
6
- const querystring = require("querystring");
7
- const request = bluebird.promisify(require("request").defaults({ jar: true }));
8
-
9
- class CustomError extends Error {
10
- constructor(obj) {
11
- if (typeof obj === 'string')
12
- obj = { message: obj };
13
- if (typeof obj !== 'object' || obj === null)
14
- throw new TypeError('Object required');
15
- obj.message ? super(obj.message) : super();
16
- Object.assign(this, obj);
17
- }
18
- }
19
-
20
- function tryPromise(tryFunc) {
21
- return new Promise((resolve, reject) => {
22
- try {
23
- resolve(tryFunc());
24
- } catch (error) {
25
- reject(error);
26
- }
27
- });
28
- }
29
-
30
- function delay(ms) {
31
- return new Promise(resolve => setTimeout(resolve, ms));
32
- }
33
-
34
- function setProxy(url) {
35
- if (typeof url == "undefined") return request = bluebird.promisify(require("request").defaults({ jar: true }));
36
- return request = bluebird.promisify(require("request").defaults({ jar: true, proxy: url }));
37
- }
38
-
39
- function getHeaders(url, options, ctx, customHeader) {
40
- var headers = {
41
- "Content-Type": "application/x-www-form-urlencoded",
42
- Referer: "https://www.facebook.com/",
43
- Host: url.replace("https://", "").split("/")[0],
44
- Origin: "https://www.facebook.com",
45
- "user-agent": (options?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36"),
46
- Connection: "keep-alive",
47
- "sec-fetch-site": 'same-origin',
48
- "sec-fetch-mode": 'cors'
49
- };
50
- if (customHeader) Object.assign(headers, customHeader);
51
- if (ctx && ctx.region) headers["X-MSGR-Region"] = ctx.region;
52
-
53
- return headers;
54
- }
55
-
56
- function isReadableStream(obj) {
57
- return (
58
- obj instanceof stream.Stream &&
59
- (getType(obj._read) === "Function" ||
60
- getType(obj._read) === "AsyncFunction") &&
61
- getType(obj._readableState) === "Object"
62
- );
63
- }
64
-
65
- function get(url, jar, qs, options, ctx) {
66
- if (getType(qs) === "Object")
67
- for (var prop in qs)
68
- if (qs.hasOwnProperty(prop) && getType(qs[prop]) === "Object") qs[prop] = JSON.stringify(qs[prop]);
69
- var op = {
70
- headers: getHeaders(url, options, ctx),
71
- timeout: 60000,
72
- qs: qs,
73
- url: url,
74
- method: "GET",
75
- jar: jar,
76
- gzip: true
77
- };
78
- return request(op).then(function (res) {
79
- return res;
80
- });
81
- }
82
-
83
- function get2(url, jar, headers, options, ctx) {
84
- var op = {
85
- headers: getHeaders(url, options, ctx, headers),
86
- timeout: 60000,
87
- url: url,
88
- method: "GET",
89
- jar: jar,
90
- gzip: true,
91
- };
92
-
93
- return request(op).then(function (res) {
94
- return res[0];
95
- });
96
- }
97
-
98
- function post(url, jar, form, options, ctx, customHeader) {
99
- var op = {
100
- headers: getHeaders(url, options),
101
- timeout: 60000,
102
- url: url,
103
- method: "POST",
104
- form: form,
105
- jar: jar,
106
- gzip: true
107
- };
108
- return request(op).then(function (res) {
109
- return res;
110
- });
111
- }
112
-
113
- function postFormData(url, jar, form, qs, options, ctx) {
114
- var headers = getHeaders(url, options, ctx);
115
- headers["Content-Type"] = "multipart/form-data";
116
- var op = {
117
- headers: headers,
118
- timeout: 60000,
119
- url: url,
120
- method: "POST",
121
- formData: form,
122
- qs: qs,
123
- jar: jar,
124
- gzip: true
125
- };
126
-
127
- return request(op).then(function (res) {
128
- return res;
129
- });
130
- }
131
-
132
- function padZeros(val, len) {
133
- val = String(val);
134
- len = len || 2;
135
- while (val.length < len) val = "0" + val;
136
- return val;
137
- }
138
-
139
- function generateThreadingID(clientID) {
140
- var k = Date.now();
141
- var l = Math.floor(Math.random() * 4294967295);
142
- var m = clientID;
143
- return "<" + k + ":" + l + "-" + m + "@mail.projektitan.com>";
144
- }
145
-
146
- function binaryToDecimal(data) {
147
- var ret = "";
148
- while (data !== "0") {
149
- var end = 0;
150
- var fullName = "";
151
- var i = 0;
152
- for (; i < data.length; i++) {
153
- end = 2 * end + parseInt(data[i], 10);
154
- if (end >= 10) {
155
- fullName += "1";
156
- end -= 10;
157
- } else fullName += "0";
158
- }
159
- ret = end.toString() + ret;
160
- data = fullName.slice(fullName.indexOf("1"));
161
- }
162
- return ret;
163
- }
164
-
165
- function generateOfflineThreadingID() {
166
- var ret = Date.now();
167
- var value = Math.floor(Math.random() * 4294967295);
168
- var str = ("0000000000000000000000" + value.toString(2)).slice(-22);
169
- var msgs = ret.toString(2) + str;
170
- return binaryToDecimal(msgs);
171
- }
172
-
173
- var h;
174
- var i = {};
175
- var j = {
176
- _: "%",
177
- A: "%2",
178
- B: "000",
179
- C: "%7d",
180
- D: "%7b%22",
181
- E: "%2c%22",
182
- F: "%22%3a",
183
- G: "%2c%22ut%22%3a1",
184
- H: "%2c%22bls%22%3a",
185
- I: "%2c%22n%22%3a%22%",
186
- J: "%22%3a%7b%22i%22%3a0%7d",
187
- K: "%2c%22pt%22%3a0%2c%22vis%22%3a",
188
- L: "%2c%22ch%22%3a%7b%22h%22%3a%22",
189
- M: "%7b%22v%22%3a2%2c%22time%22%3a1",
190
- N: ".channel%22%2c%22sub%22%3a%5b",
191
- O: "%2c%22sb%22%3a1%2c%22t%22%3a%5b",
192
- P: "%2c%22ud%22%3a100%2c%22lc%22%3a0",
193
- Q: "%5d%2c%22f%22%3anull%2c%22uct%22%3a",
194
- R: ".channel%22%2c%22sub%22%3a%5b1%5d",
195
- S: "%22%2c%22m%22%3a0%7d%2c%7b%22i%22%3a",
196
- T: "%2c%22blc%22%3a1%2c%22snd%22%3a1%2c%22ct%22%3a",
197
- U: "%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a",
198
- V: "%2c%22blc%22%3a0%2c%22snd%22%3a0%2c%22ct%22%3a",
199
- W: "%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a",
200
- X: "%2c%22ri%22%3a0%7d%2c%22state%22%3a%7b%22p%22%3a0%2c%22ut%22%3a1",
201
- 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",
202
- 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"
203
- };
204
- (function () {
205
- var l = [];
206
- for (var m in j) {
207
- i[j[m]] = m;
208
- l.push(j[m]);
209
- }
210
- l.reverse();
211
- h = new RegExp(l.join("|"), "g");
212
- })();
213
-
214
- function presenceEncode(str) {
215
- return encodeURIComponent(str)
216
- .replace(/([_A-Z])|%../g, function (m, n) {
217
- return n ? "%" + n.charCodeAt(0).toString(16) : m;
218
- })
219
- .toLowerCase()
220
- .replace(h, function (m) {
221
- return i[m];
222
- });
223
- }
224
-
225
- function presenceDecode(str) {
226
- return decodeURIComponent(
227
- str.replace(/[_A-Z]/g, function (/** @type {string | number} */m) {
228
- return j[m];
229
- })
230
- );
231
- }
232
-
233
- function generatePresence(userID) {
234
- var time = Date.now();
235
- return (
236
- "E" +
237
- presenceEncode(
238
- JSON.stringify({
239
- v: 3,
240
- time: parseInt(time / 1000, 10),
241
- user: userID,
242
- state: {
243
- ut: 0,
244
- t2: [],
245
- lm2: null,
246
- uct2: time,
247
- tr: null,
248
- tw: Math.floor(Math.random() * 4294967295) + 1,
249
- at: time
250
- },
251
- ch: {
252
- ["p_" + userID]: 0
253
- }
254
- })
255
- )
256
- );
257
- }
258
-
259
- function generateAccessiblityCookie() {
260
- var time = Date.now();
261
- return encodeURIComponent(
262
- JSON.stringify({
263
- sr: 0,
264
- "sr-ts": time,
265
- jk: 0,
266
- "jk-ts": time,
267
- kb: 0,
268
- "kb-ts": time,
269
- hcm: 0,
270
- "hcm-ts": time
271
- })
272
- );
273
- }
274
-
275
- function getGUID() {
276
- /** @type {number} */
277
-
278
- var sectionLength = Date.now();
279
- /** @type {string} */
280
-
281
- var id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
282
- /** @type {number} */
283
-
284
- var r = Math.floor((sectionLength + Math.random() * 16) % 16);
285
- /** @type {number} */
286
-
287
- sectionLength = Math.floor(sectionLength / 16);
288
- /** @type {string} */
289
-
290
- var _guid = (c == "x" ? r : (r & 7) | 8).toString(16);
291
- return _guid;
292
- });
293
- return id;
294
- }
295
-
296
- function _formatAttachment(attachment1, attachment2) {
297
- attachment2 = attachment2 || { id: "", image_data: {} };
298
- attachment1 = attachment1.mercury ? attachment1.mercury : attachment1;
299
- var blob = attachment1.blob_attachment;
300
- var type =
301
- blob && blob.__typename ? blob.__typename : attachment1.attach_type;
302
- if (!type && attachment1.sticker_attachment) {
303
- type = "StickerAttachment";
304
- blob = attachment1.sticker_attachment;
305
- } else if (!type && attachment1.extensible_attachment) {
306
- if (
307
- attachment1.extensible_attachment.story_attachment &&
308
- attachment1.extensible_attachment.story_attachment.target &&
309
- attachment1.extensible_attachment.story_attachment.target.__typename &&
310
- attachment1.extensible_attachment.story_attachment.target.__typename === "MessageLocation"
311
- ) type = "MessageLocation";
312
- else type = "ExtensibleAttachment";
313
-
314
- blob = attachment1.extensible_attachment;
315
- }
316
- switch (type) {
317
- case "sticker":
318
- return {
319
- type: "sticker",
320
- ID: attachment1.metadata.stickerID.toString(),
321
- url: attachment1.url,
322
-
323
- packID: attachment1.metadata.packID.toString(),
324
- spriteUrl: attachment1.metadata.spriteURI,
325
- spriteUrl2x: attachment1.metadata.spriteURI2x,
326
- width: attachment1.metadata.width,
327
- height: attachment1.metadata.height,
328
-
329
- caption: attachment2.caption,
330
- description: attachment2.description,
331
-
332
- frameCount: attachment1.metadata.frameCount,
333
- frameRate: attachment1.metadata.frameRate,
334
- framesPerRow: attachment1.metadata.framesPerRow,
335
- framesPerCol: attachment1.metadata.framesPerCol,
336
-
337
- stickerID: attachment1.metadata.stickerID.toString(), // @Legacy
338
- spriteURI: attachment1.metadata.spriteURI, // @Legacy
339
- spriteURI2x: attachment1.metadata.spriteURI2x // @Legacy
340
- };
341
- case "file":
342
- return {
343
- type: "file",
344
- filename: attachment1.name,
345
- ID: attachment2.id.toString(),
346
- url: attachment1.url,
347
-
348
- isMalicious: attachment2.is_malicious,
349
- contentType: attachment2.mime_type,
350
-
351
- name: attachment1.name, // @Legacy
352
- mimeType: attachment2.mime_type, // @Legacy
353
- fileSize: attachment2.file_size // @Legacy
354
- };
355
- case "photo":
356
- return {
357
- type: "photo",
358
- ID: attachment1.metadata.fbid.toString(),
359
- filename: attachment1.fileName,
360
- thumbnailUrl: attachment1.thumbnail_url,
361
-
362
- previewUrl: attachment1.preview_url,
363
- previewWidth: attachment1.preview_width,
364
- previewHeight: attachment1.preview_height,
365
-
366
- largePreviewUrl: attachment1.large_preview_url,
367
- largePreviewWidth: attachment1.large_preview_width,
368
- largePreviewHeight: attachment1.large_preview_height,
369
-
370
- url: attachment1.metadata.url, // @Legacy
371
- width: attachment1.metadata.dimensions.split(",")[0], // @Legacy
372
- height: attachment1.metadata.dimensions.split(",")[1], // @Legacy
373
- name: attachment1.fileName // @Legacy
374
- };
375
- case "animated_image":
376
- return {
377
- type: "animated_image",
378
- ID: attachment2.id.toString(),
379
- filename: attachment2.filename,
380
-
381
- previewUrl: attachment1.preview_url,
382
- previewWidth: attachment1.preview_width,
383
- previewHeight: attachment1.preview_height,
384
-
385
- url: attachment2.image_data.url,
386
- width: attachment2.image_data.width,
387
- height: attachment2.image_data.height,
388
-
389
- name: attachment1.name, // @Legacy
390
- facebookUrl: attachment1.url, // @Legacy
391
- thumbnailUrl: attachment1.thumbnail_url, // @Legacy
392
- mimeType: attachment2.mime_type, // @Legacy
393
- rawGifImage: attachment2.image_data.raw_gif_image, // @Legacy
394
- rawWebpImage: attachment2.image_data.raw_webp_image, // @Legacy
395
- animatedGifUrl: attachment2.image_data.animated_gif_url, // @Legacy
396
- animatedGifPreviewUrl: attachment2.image_data.animated_gif_preview_url, // @Legacy
397
- animatedWebpUrl: attachment2.image_data.animated_webp_url, // @Legacy
398
- animatedWebpPreviewUrl: attachment2.image_data.animated_webp_preview_url // @Legacy
399
- };
400
- case "share":
401
- return {
402
- type: "share",
403
- ID: attachment1.share.share_id.toString(),
404
- url: attachment2.href,
405
-
406
- title: attachment1.share.title,
407
- description: attachment1.share.description,
408
- source: attachment1.share.source,
409
-
410
- image: attachment1.share.media.image,
411
- width: attachment1.share.media.image_size.width,
412
- height: attachment1.share.media.image_size.height,
413
- playable: attachment1.share.media.playable,
414
- duration: attachment1.share.media.duration,
415
-
416
- subattachments: attachment1.share.subattachments,
417
- properties: {},
418
-
419
- animatedImageSize: attachment1.share.media.animated_image_size, // @Legacy
420
- facebookUrl: attachment1.share.uri, // @Legacy
421
- target: attachment1.share.target, // @Legacy
422
- styleList: attachment1.share.style_list // @Legacy
423
- };
424
- case "video":
425
- return {
426
- type: "video",
427
- ID: attachment1.metadata.fbid.toString(),
428
- filename: attachment1.name,
429
-
430
- previewUrl: attachment1.preview_url,
431
- previewWidth: attachment1.preview_width,
432
- previewHeight: attachment1.preview_height,
433
-
434
- url: attachment1.url,
435
- width: attachment1.metadata.dimensions.width,
436
- height: attachment1.metadata.dimensions.height,
437
-
438
- duration: attachment1.metadata.duration,
439
- videoType: "unknown",
440
-
441
- thumbnailUrl: attachment1.thumbnail_url // @Legacy
442
- };
443
- case "error":
444
- return {
445
- type: "error",
446
- attachment1: attachment1,
447
- attachment2: attachment2
448
- };
449
- case "MessageImage":
450
- return {
451
- type: "photo",
452
- ID: blob.legacy_attachment_id,
453
- filename: blob.filename,
454
- thumbnailUrl: blob.thumbnail.uri,
455
-
456
- previewUrl: blob.preview.uri,
457
- previewWidth: blob.preview.width,
458
- previewHeight: blob.preview.height,
459
-
460
- largePreviewUrl: blob.large_preview.uri,
461
- largePreviewWidth: blob.large_preview.width,
462
- largePreviewHeight: blob.large_preview.height,
463
-
464
- url: blob.large_preview.uri, // @Legacy
465
- width: blob.original_dimensions.x, // @Legacy
466
- height: blob.original_dimensions.y, // @Legacy
467
- name: blob.filename // @Legacy
468
- };
469
- case "MessageAnimatedImage":
470
- return {
471
- type: "animated_image",
472
- ID: blob.legacy_attachment_id,
473
- filename: blob.filename,
474
-
475
- previewUrl: blob.preview_image.uri,
476
- previewWidth: blob.preview_image.width,
477
- previewHeight: blob.preview_image.height,
478
-
479
- url: blob.animated_image.uri,
480
- width: blob.animated_image.width,
481
- height: blob.animated_image.height,
482
-
483
- thumbnailUrl: blob.preview_image.uri, // @Legacy
484
- name: blob.filename, // @Legacy
485
- facebookUrl: blob.animated_image.uri, // @Legacy
486
- rawGifImage: blob.animated_image.uri, // @Legacy
487
- animatedGifUrl: blob.animated_image.uri, // @Legacy
488
- animatedGifPreviewUrl: blob.preview_image.uri, // @Legacy
489
- animatedWebpUrl: blob.animated_image.uri, // @Legacy
490
- animatedWebpPreviewUrl: blob.preview_image.uri // @Legacy
491
- };
492
- case "MessageVideo":
493
- return {
494
- type: "video",
495
- filename: blob.filename,
496
- ID: blob.legacy_attachment_id,
497
-
498
- previewUrl: blob.large_image.uri,
499
- previewWidth: blob.large_image.width,
500
- previewHeight: blob.large_image.height,
501
-
502
- url: blob.playable_url,
503
- width: blob.original_dimensions.x,
504
- height: blob.original_dimensions.y,
505
-
506
- duration: blob.playable_duration_in_ms,
507
- videoType: blob.video_type.toLowerCase(),
508
-
509
- thumbnailUrl: blob.large_image.uri // @Legacy
510
- };
511
- case "MessageAudio":
512
- return {
513
- type: "audio",
514
- filename: blob.filename,
515
- ID: blob.url_shimhash,
516
-
517
- audioType: blob.audio_type,
518
- duration: blob.playable_duration_in_ms,
519
- url: blob.playable_url,
520
-
521
- isVoiceMail: blob.is_voicemail
522
- };
523
- case "StickerAttachment":
524
- return {
525
- type: "sticker",
526
- ID: blob.id,
527
- url: blob.url,
528
-
529
- packID: blob.pack ? blob.pack.id : null,
530
- spriteUrl: blob.sprite_image,
531
- spriteUrl2x: blob.sprite_image_2x,
532
- width: blob.width,
533
- height: blob.height,
534
-
535
- caption: blob.label,
536
- description: blob.label,
537
-
538
- frameCount: blob.frame_count,
539
- frameRate: blob.frame_rate,
540
- framesPerRow: blob.frames_per_row,
541
- framesPerCol: blob.frames_per_column,
542
-
543
- stickerID: blob.id, // @Legacy
544
- spriteURI: blob.sprite_image, // @Legacy
545
- spriteURI2x: blob.sprite_image_2x // @Legacy
546
- };
547
- case "MessageLocation":
548
- var urlAttach = blob.story_attachment.url;
549
- var mediaAttach = blob.story_attachment.media;
550
-
551
- var u = querystring.parse(url.parse(urlAttach).query).u;
552
- var where1 = querystring.parse(url.parse(u).query).where1;
553
- var address = where1.split(", ");
554
-
555
- var latitude;
556
- var longitude;
557
-
558
- try {
559
- latitude = Number.parseFloat(address[0]);
560
- longitude = Number.parseFloat(address[1]);
561
- } catch (err) {
562
- /* empty */
563
-
564
- }
565
-
566
- var imageUrl;
567
- var width;
568
- var height;
569
-
570
- if (mediaAttach && mediaAttach.image) {
571
- imageUrl = mediaAttach.image.uri;
572
- width = mediaAttach.image.width;
573
- height = mediaAttach.image.height;
574
- }
575
-
576
- return {
577
- type: "location",
578
- ID: blob.legacy_attachment_id,
579
- latitude: latitude,
580
- longitude: longitude,
581
- image: imageUrl,
582
- width: width,
583
- height: height,
584
- url: u || urlAttach,
585
- address: where1,
586
-
587
- facebookUrl: blob.story_attachment.url, // @Legacy
588
- target: blob.story_attachment.target, // @Legacy
589
- styleList: blob.story_attachment.style_list // @Legacy
590
- };
591
- case "ExtensibleAttachment":
592
- return {
593
- type: "share",
594
- ID: blob.legacy_attachment_id,
595
- url: blob.story_attachment.url,
596
-
597
- title: blob.story_attachment.title_with_entities.text,
598
- description: blob.story_attachment.description &&
599
- blob.story_attachment.description.text,
600
- source: blob.story_attachment.source ? blob.story_attachment.source.text : null,
601
-
602
- image: blob.story_attachment.media &&
603
- blob.story_attachment.media.image &&
604
- blob.story_attachment.media.image.uri,
605
- width: blob.story_attachment.media &&
606
- blob.story_attachment.media.image &&
607
- blob.story_attachment.media.image.width,
608
- height: blob.story_attachment.media &&
609
- blob.story_attachment.media.image &&
610
- blob.story_attachment.media.image.height,
611
- playable: blob.story_attachment.media &&
612
- blob.story_attachment.media.is_playable,
613
- duration: blob.story_attachment.media &&
614
- blob.story_attachment.media.playable_duration_in_ms,
615
- playableUrl: blob.story_attachment.media == null ? null : blob.story_attachment.media.playable_url,
616
-
617
- subattachments: blob.story_attachment.subattachments,
618
- properties: blob.story_attachment.properties.reduce(function (/** @type {{ [x: string]: any; }} */obj, /** @type {{ key: string | number; value: { text: any; }; }} */cur) {
619
- obj[cur.key] = cur.value.text;
620
- return obj;
621
- }, {}),
622
-
623
- facebookUrl: blob.story_attachment.url, // @Legacy
624
- target: blob.story_attachment.target, // @Legacy
625
- styleList: blob.story_attachment.style_list // @Legacy
626
- };
627
- case "MessageFile":
628
- return {
629
- type: "file",
630
- filename: blob.filename,
631
- ID: blob.message_file_fbid,
632
-
633
- url: blob.url,
634
- isMalicious: blob.is_malicious,
635
- contentType: blob.content_type,
636
-
637
- name: blob.filename,
638
- mimeType: "",
639
- fileSize: -1
640
- };
641
- default:
642
- throw new Error(
643
- "unrecognized attach_file of type " +
644
- type +
645
- "`" +
646
- JSON.stringify(attachment1, null, 4) +
647
- " attachment2: " +
648
- JSON.stringify(attachment2, null, 4) +
649
- "`"
650
- );
651
- }
652
- }
653
-
654
- function formatAttachment(attachments, attachmentIds, attachmentMap, shareMap) {
655
- attachmentMap = shareMap || attachmentMap;
656
- return attachments ?
657
- attachments.map(function (i) {
658
- if (!attachmentMap ||
659
- !attachmentIds ||
660
- !attachmentMap[attachmentIds[i]]
661
- ) {
662
- return _formatAttachment(val);
663
- }
664
- return _formatAttachment(val, attachmentMap[attachmentIds[i]]);
665
- }) : [];
666
- }
667
-
668
- function formatDeltaMessage(m) {
669
- var md = m.messageMetadata;
670
- var mdata =
671
- m.data === undefined ? [] :
672
- m.data.prng === undefined ? [] :
673
- JSON.parse(m.data.prng);
674
- var m_id = mdata.map((/** @type {{ i: any; }} */u) => u.i);
675
- var m_offset = mdata.map((/** @type {{ o: any; }} */u) => u.o);
676
- var m_length = mdata.map((/** @type {{ l: any; }} */u) => u.l);
677
- var mentions = {};
678
- var body = m.body || "";
679
- var args = body == "" ? [] : body.trim().split(/\s+/);
680
- for (var i = 0; i < m_id.length; i++) mentions[m_id[i]] = m.body.substring(m_offset[i], m_offset[i] + m_length[i]);
681
- return {
682
- type: "message",
683
- senderID: formatID(md.actorFbId.toString()),
684
- threadID: formatID((md.threadKey.threadFbId || md.threadKey.otherUserFbId).toString()),
685
- messageID: md.messageId,
686
- args: args,
687
- body: body,
688
- attachments: (m.attachments || []).map((/** @type {any} */v) => _formatAttachment(v)),
689
- mentions: mentions,
690
- timestamp: md.timestamp,
691
- isGroup: !!md.threadKey.threadFbId,
692
- participantIDs: m.participants || []
693
- };
694
- }
695
-
696
- function formatID(id) {
697
- if (id != undefined && id != null) return id.replace(/(fb)?id[:.]/, "");
698
- else return id;
699
- }
700
-
701
- function formatMessage(m) {
702
- var originalMessage = m.message ? m.message : m;
703
- var obj = {
704
- type: "message",
705
- senderName: originalMessage.sender_name,
706
- senderID: formatID(originalMessage.sender_fbid.toString()),
707
- participantNames: originalMessage.group_thread_info ? originalMessage.group_thread_info.participant_names : [originalMessage.sender_name.split(" ")[0]],
708
- participantIDs: originalMessage.group_thread_info ?
709
- originalMessage.group_thread_info.participant_ids.map(function (v) {
710
- return formatID(v.toString());
711
- }) : [formatID(originalMessage.sender_fbid)],
712
- body: originalMessage.body || "",
713
- threadID: formatID((originalMessage.thread_fbid || originalMessage.other_user_fbid).toString()),
714
- threadName: originalMessage.group_thread_info ? originalMessage.group_thread_info.name : originalMessage.sender_name,
715
- location: originalMessage.coordinates ? originalMessage.coordinates : null,
716
- messageID: originalMessage.mid ? originalMessage.mid.toString() : originalMessage.message_id,
717
- attachments: formatAttachment(
718
- originalMessage.attachments,
719
- originalMessage.attachmentIds,
720
- originalMessage.attachment_map,
721
- originalMessage.share_map
722
- ),
723
- timestamp: originalMessage.timestamp,
724
- timestampAbsolute: originalMessage.timestamp_absolute,
725
- timestampRelative: originalMessage.timestamp_relative,
726
- timestampDatetime: originalMessage.timestamp_datetime,
727
- tags: originalMessage.tags,
728
- reactions: originalMessage.reactions ? originalMessage.reactions : [],
729
- isUnread: originalMessage.is_unread
730
- };
731
- if (m.type === "pages_messaging") obj.pageID = m.realtime_viewer_fbid.toString();
732
- obj.isGroup = obj.participantIDs.length > 2;
733
- return obj;
734
- }
735
-
736
- function formatEvent(m) {
737
- var originalMessage = m.message ? m.message : m;
738
- var logMessageType = originalMessage.log_message_type;
739
- var logMessageData;
740
- if (logMessageType === "log:generic-admin-text") {
741
- logMessageData = originalMessage.log_message_data.untypedData;
742
- logMessageType = getAdminTextMessageType(originalMessage.log_message_data.message_type);
743
- } else logMessageData = originalMessage.log_message_data;
744
- return Object.assign(formatMessage(originalMessage), {
745
- type: "event",
746
- logMessageType: logMessageType,
747
- logMessageData: logMessageData,
748
- logMessageBody: originalMessage.log_message_body
749
- });
750
- }
751
-
752
- function formatHistoryMessage(m) {
753
- switch (m.action_type) {
754
- case "ma-type:log-message":
755
- return formatEvent(m);
756
- default:
757
- return formatMessage(m);
758
- }
759
- }
760
-
761
- function getAdminTextMessageType(m) {
762
- switch (m.type) {
763
- case "joinable_group_link_mode_change":
764
- return "log:link-status";
765
- case "magic_words":
766
- return "log:magic-words";
767
- case "change_thread_theme":
768
- return "log:thread-color";
769
- case "change_thread_icon":
770
- case "change_thread_quick_reaction":
771
- return "log:thread-icon";
772
- case "change_thread_nickname":
773
- return "log:user-nickname";
774
- case "change_thread_admins":
775
- return "log:thread-admins";
776
- case "group_poll":
777
- return "log:thread-poll";
778
- case "change_thread_approval_mode":
779
- return "log:thread-approval-mode";
780
- case "messenger_call_log":
781
- case "participant_joined_group_call":
782
- return "log:thread-call";
783
- case "pin_messages_v2":
784
- return "log:thread-pinned";
785
- case 'unpin_messages_v2':
786
- return 'log:unpin-message';
787
- default:
788
- return m.type;
789
- }
790
- }
791
-
792
- function formatDeltaEvent(m) {
793
- var logMessageType;
794
- var logMessageData;
795
- switch (m.class) {
796
- case "AdminTextMessage":
797
- logMessageType = getAdminTextMessageType(m);
798
- logMessageData = m.untypedData;
799
- break;
800
- case "ThreadName":
801
- logMessageType = "log:thread-name";
802
- logMessageData = { name: m.name };
803
- break;
804
- case "ParticipantsAddedToGroupThread":
805
- logMessageType = "log:subscribe";
806
- logMessageData = { addedParticipants: m.addedParticipants };
807
- break;
808
- case "ParticipantLeftGroupThread":
809
- logMessageType = "log:unsubscribe";
810
- logMessageData = { leftParticipantFbId: m.leftParticipantFbId };
811
- break;
812
- case "UserLocation": {
813
- logMessageType = "log:user-location";
814
- logMessageData = {
815
- Image: m.attachments[0].mercury.extensible_attachment.story_attachment.media.image,
816
- Location: m.attachments[0].mercury.extensible_attachment.story_attachment.target.location_title,
817
- coordinates: m.attachments[0].mercury.extensible_attachment.story_attachment.target.coordinate,
818
- url: m.attachments[0].mercury.extensible_attachment.story_attachment.url
819
- };
820
- }
821
- case "ApprovalQueue":
822
- logMessageType = "log:approval-queue";
823
- logMessageData = {
824
- approvalQueue: {
825
- action: m.action,
826
- recipientFbId: m.recipientFbId,
827
- requestSource: m.requestSource,
828
- ...m.messageMetadata
829
- }
830
- };
831
- }
832
- return {
833
- type: "event",
834
- threadID: formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),
835
- logMessageType: logMessageType,
836
- logMessageData: logMessageData,
837
- logMessageBody: m.messageMetadata.adminText,
838
- author: m.messageMetadata.actorFbId,
839
- participantIDs: (m?.participants || []).map((e) => e.toString())
840
- };
841
- }
842
-
843
- function formatTyp(event) {
844
- return {
845
- isTyping: !!event.st,
846
- from: event.from.toString(),
847
- threadID: formatID((event.to || event.thread_fbid || event.from).toString()),
848
- fromMobile: event.hasOwnProperty("from_mobile") ? event.from_mobile : true,
849
- userID: (event.realtime_viewer_fbid || event.from).toString(),
850
- type: "typ"
851
- };
852
- }
853
-
854
- function formatDeltaReadReceipt(delta) {
855
- return {
856
- reader: (delta.threadKey.otherUserFbId || delta.actorFbId).toString(),
857
- time: delta.actionTimestampMs,
858
- threadID: formatID((delta.threadKey.otherUserFbId || delta.threadKey.threadFbId).toString()),
859
- type: "read_receipt"
860
- };
861
- }
862
-
863
- function formatReadReceipt(event) {
864
- return {
865
- reader: event.reader.toString(),
866
- time: event.time,
867
- threadID: formatID((event.thread_fbid || event.reader).toString()),
868
- type: "read_receipt"
869
- };
870
- }
871
-
872
- function formatRead(event) {
873
- return {
874
- threadID: formatID(((event.chat_ids && event.chat_ids[0]) || (event.thread_fbids && event.thread_fbids[0])).toString()),
875
- time: event.timestamp,
876
- type: "read"
877
- };
878
- }
879
-
880
- function getFrom(str, startToken, endToken) {
881
- var start = str.indexOf(startToken) + startToken.length;
882
- if (start < startToken.length) return "";
883
- var lastHalf = str.substring(start);
884
- var end = lastHalf.indexOf(endToken);
885
- if (end === -1) throw Error("Could not find endTime `" + endToken + "` in the given string.");
886
- return lastHalf.substring(0, end);
887
- }
888
-
889
- function getFroms(str, startToken, endToken) {
890
- let results = [];
891
- let currentIndex = 0;
892
- while (true) {
893
- let start = str.indexOf(startToken, currentIndex);
894
- if (start === -1) break;
895
- start += startToken.length;
896
- let lastHalf = str.substring(start);
897
- let end = lastHalf.indexOf(endToken);
898
- if (end === -1) {
899
- if (results.length === 0) {
900
- throw Error("Could not find endToken `" + endToken + "` in the given string.");
901
- }
902
- break;
903
- }
904
- results.push(lastHalf.substring(0, end));
905
- currentIndex = start + end + endToken.length;
906
- }
907
- return results.length === 0 ? "" : results.length === 1 ? results[0] : results;
908
- }
909
-
910
- function makeParsable(html) {
911
- let withoutForLoop = html.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, "");
912
- let maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
913
- if (maybeMultipleObjects.length === 1) return maybeMultipleObjects;
914
- return "[" + maybeMultipleObjects.join("},{") + "]";
915
- }
916
-
917
- function arrToForm(form) {
918
- return arrayToObject(form,
919
- function (v) {
920
- return v.name;
921
- },
922
- function (v) {
923
- return v.val;
924
- }
925
- );
926
- }
927
-
928
- function arrayToObject(arr, getKey, getValue) {
929
- return arr.reduce(function (acc, val) {
930
- acc[getKey(val)] = getValue(val);
931
- return acc;
932
- }, {});
933
- }
934
-
935
- function getSignatureID() {
936
- return Math.floor(Math.random() * 2147483648).toString(16);
937
- }
938
-
939
- function generateTimestampRelative() {
940
- var d = new Date();
941
- return d.getHours() + ":" + padZeros(d.getMinutes());
942
- }
943
-
944
- function makeDefaults(html, userID, ctx) {
945
- var reqCounter = 1;
946
- const fb_dtsg = getFrom(html, '"DTSGInitData",[],{"token":"', '",');
947
- var ttstamp = "2";
948
- for (var i = 0; i < fb_dtsg.length; i++) ttstamp += fb_dtsg.charCodeAt(i);
949
- var revision = getFrom(html, 'revision":', ",");
950
- function mergeWithDefaults(obj) {
951
- var newObj = {
952
- __user: userID,
953
- __req: (reqCounter++).toString(36),
954
- __rev: revision,
955
- __a: 1,
956
- fb_dtsg: ctx.fb_dtsg ? ctx.fb_dtsg : fb_dtsg,
957
- jazoest: ctx.ttstamp ? ctx.ttstamp : ttstamp
958
- };
959
- if (!obj) return newObj;
960
- for (var prop in obj)
961
- if (obj.hasOwnProperty(prop))
962
- if (!newObj[prop]) newObj[prop] = obj[prop];
963
- return newObj;
964
- }
965
- function postWithDefaults(url, jar, form, ctxx) {
966
- return post(url, jar, mergeWithDefaults(form), ctx.globalOptions, ctxx || ctx);
967
- }
968
- function getWithDefaults(url, jar, qs, ctxx) {
969
- return get(url, jar, mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
970
- }
971
- function postFormDataWithDefault(url, jar, form, qs, ctxx) {
972
- return postFormData(url, jar, mergeWithDefaults(form), mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
973
- }
974
- return {
975
- get: getWithDefaults,
976
- post: postWithDefaults,
977
- postFormData: postFormDataWithDefault
978
- };
979
- }
980
-
981
- function parseAndCheckLogin(ctx, defaultFuncs, retryCount = 0, sourceCall) {
982
- if (sourceCall === undefined) {
983
- try {
984
- throw new Error();
985
- } catch (e) {
986
- sourceCall = e;
987
- }
988
- }
989
- return function (data) {
990
- return tryPromise(function () {
991
- log.verbose("parseAndCheckLogin", data.body);
992
- if (data.statusCode >= 500 && data.statusCode < 600) {
993
- if (retryCount >= 5) {
994
- throw {
995
- message: "Request retry failed. Check `res` and `statusCode`.",
996
- statusCode: data.statusCode,
997
- res: data.body,
998
- error: "Request retry failed.",
999
- sourceCall
1000
- };
1001
- }
1002
- retryCount++;
1003
- const retryTime = Math.floor(Math.random() * 5000);
1004
- log.warn(
1005
- "parseAndCheckLogin",
1006
- `Got status code ${data.statusCode} - Retrying in ${retryTime}ms...`
1007
- );
1008
- if (!data.request) throw new Error("Invalid request object");
1009
- const url = `${data.request.uri.protocol}//${data.request.uri.hostname}${data.request.uri.pathname}`;
1010
- const contentType = data.request.headers?.["content-type"]?.split(";")[0];
1011
- return delay(retryTime)
1012
- .then(() =>
1013
- contentType === "multipart/form-data"
1014
- ? defaultFuncs.postFormData(url, ctx.jar, data.request.formData, {})
1015
- : defaultFuncs.post(url, ctx.jar, data.request.formData)
1016
- )
1017
- .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount, sourceCall));
1018
- }
1019
- if (data.statusCode !== 200) {
1020
- throw {
1021
- message: `parseAndCheckLogin got status code: ${data.statusCode}.`,
1022
- statusCode: data.statusCode,
1023
- res: data.body,
1024
- error: `parseAndCheckLogin got status code: ${data.statusCode}.`,
1025
- sourceCall
1026
- };
1027
- }
1028
- let res;
1029
- try {
1030
- res = JSON.parse(makeParsable(data.body));
1031
- } catch (e) {
1032
- log.error("JSON parsing failed:", data.body);
1033
- throw {
1034
- message: "Failed to parse JSON response.",
1035
- detail: e.message,
1036
- res: data.body,
1037
- error: "JSON.parse error.",
1038
- sourceCall
1039
- };
1040
- }
1041
- if (res.redirect && data.request.method === "GET") {
1042
- return defaultFuncs
1043
- .get(res.redirect, ctx.jar)
1044
- .then(parseAndCheckLogin(ctx, defaultFuncs, undefined, sourceCall));
1045
- }
1046
- if (
1047
- res.jsmods?.require &&
1048
- Array.isArray(res.jsmods.require[0]) &&
1049
- res.jsmods.require[0][0] === "Cookie"
1050
- ) {
1051
- res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
1052
- const cookie = formatCookie(res.jsmods.require[0][3], "facebook");
1053
- const cookie2 = formatCookie(res.jsmods.require[0][3], "messenger");
1054
- ctx.jar.setCookie(cookie, "https://www.facebook.com");
1055
- ctx.jar.setCookie(cookie2, "https://www.messenger.com");
1056
- }
1057
- if (res.jsmods?.require) {
1058
- for (const arr of res.jsmods.require) {
1059
- if (arr[0] === "DTSG" && arr[1] === "setToken") {
1060
- ctx.fb_dtsg = arr[3][0];
1061
- ctx.ttstamp = "2" + ctx.fb_dtsg.split("").map(c => c.charCodeAt(0)).join("");
1062
- }
1063
- }
1064
- }
1065
- if (res.error === 1357001) {
1066
- if (!ctx.auto_login) {
1067
- ctx.auto_login = true;
1068
- auto_login(success => {
1069
- if (success) {
1070
- log.info("Auto login successful! Retrying...");
1071
- ctx.auto_login = false;
1072
- process.exit(1);
1073
- } else {
1074
- ctx.auto_login = false;
1075
- throw {
1076
- message: "Facebook blocked login. Please check your account.",
1077
- error: "Not logged in.",
1078
- res,
1079
- statusCode: data.statusCode,
1080
- sourceCall
1081
- };
1082
- }
1083
- });
1084
- }
1085
- }
1086
- return res;
1087
- });
1088
- };
1089
- }
1090
- function saveCookies(jar) {
1091
- return function (res) {
1092
- var cookies = res.headers["set-cookie"] || [];
1093
- cookies.forEach(function (c) {
1094
- if (c.indexOf(".facebook.com") > -1) {
1095
- jar.setCookie(c, "https://www.facebook.com");
1096
- jar.setCookie(c.replace(/domain=\.facebook\.com/, "domain=.messenger.com"), "https://www.messenger.com");
1097
- }
1098
- });
1099
- return res;
1100
- };
1101
- }
1102
-
1103
- var NUM_TO_MONTH = [
1104
- "Jan",
1105
- "Feb",
1106
- "Mar",
1107
- "Apr",
1108
- "May",
1109
- "Jun",
1110
- "Jul",
1111
- "Aug",
1112
- "Sep",
1113
- "Oct",
1114
- "Nov",
1115
- "Dec"
1116
- ];
1117
- var NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
1118
-
1119
- function formatDate(date) {
1120
- var d = date.getUTCDate();
1121
- d = d >= 10 ? d : "0" + d;
1122
- var h = date.getUTCHours();
1123
- h = h >= 10 ? h : "0" + h;
1124
- var m = date.getUTCMinutes();
1125
- m = m >= 10 ? m : "0" + m;
1126
- var s = date.getUTCSeconds();
1127
- s = s >= 10 ? s : "0" + s;
1128
- return (NUM_TO_DAY[date.getUTCDay()] + ", " + d + " " + NUM_TO_MONTH[date.getUTCMonth()] + " " + date.getUTCFullYear() + " " + h + ":" + m + ":" + s + " GMT");
1129
- }
1130
-
1131
- function formatCookie(arr, url) {
1132
- return arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + url + ".com";
1133
- }
1134
-
1135
- function formatThread(data) {
1136
- return {
1137
- threadID: formatID(data.thread_fbid.toString()),
1138
- participants: data.participants.map(formatID),
1139
- participantIDs: data.participants.map(formatID),
1140
- name: data.name,
1141
- nicknames: data.custom_nickname,
1142
- snippet: data.snippet,
1143
- snippetAttachments: data.snippet_attachments,
1144
- snippetSender: formatID((data.snippet_sender || "").toString()),
1145
- unreadCount: data.unread_count,
1146
- messageCount: data.message_count,
1147
- imageSrc: data.image_src,
1148
- timestamp: data.timestamp,
1149
- muteUntil: data.mute_until,
1150
- isCanonicalUser: data.is_canonical_user,
1151
- isCanonical: data.is_canonical,
1152
- isSubscribed: data.is_subscribed,
1153
- folder: data.folder,
1154
- isArchived: data.is_archived,
1155
- recipientsLoadable: data.recipients_loadable,
1156
- hasEmailParticipant: data.has_email_participant,
1157
- readOnly: data.read_only,
1158
- canReply: data.can_reply,
1159
- cannotReplyReason: data.cannot_reply_reason,
1160
- lastMessageTimestamp: data.last_message_timestamp,
1161
- lastReadTimestamp: data.last_read_timestamp,
1162
- lastMessageType: data.last_message_type,
1163
- emoji: data.custom_like_icon,
1164
- color: data.custom_color,
1165
- adminIDs: data.admin_ids,
1166
- threadType: data.thread_type
1167
- };
1168
- }
1169
-
1170
- function getType(obj) {
1171
- return Object.prototype.toString.call(obj).slice(8, -1);
1172
- }
1173
-
1174
- function formatProxyPresence(presence, userID) {
1175
- if (presence.lat === undefined || presence.p === undefined) return null;
1176
- return {
1177
- type: "presence",
1178
- timestamp: presence.lat * 1000,
1179
- userID: userID || '',
1180
- statuses: presence.p
1181
- };
1182
- }
1183
-
1184
- function formatPresence(presence, userID) {
1185
- return {
1186
- type: "presence",
1187
- timestamp: presence.la * 1000,
1188
- userID: userID || '',
1189
- statuses: presence.a
1190
- };
1191
- }
1192
-
1193
- function decodeClientPayload(payload) {
1194
- function Utf8ArrayToStr(array) {
1195
- var out, i, len, c;
1196
- var char2, char3;
1197
- out = "";
1198
- len = array.length;
1199
- i = 0;
1200
- while (i < len) {
1201
- c = array[i++];
1202
- switch (c >> 4) {
1203
- case 0:
1204
- case 1:
1205
- case 2:
1206
- case 3:
1207
- case 4:
1208
- case 5:
1209
- case 6:
1210
- case 7:
1211
- out += String.fromCharCode(c);
1212
- break;
1213
- case 12:
1214
- case 13:
1215
- char2 = array[i++];
1216
- out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
1217
- break;
1218
- case 14:
1219
- char2 = array[i++];
1220
- char3 = array[i++];
1221
- out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
1222
- break;
1223
- }
1224
- }
1225
- return out;
1226
- }
1227
- return JSON.parse(Utf8ArrayToStr(payload));
1228
- }
1229
-
1230
- function getAppState(jar) {
1231
- return jar.getCookies("https://www.facebook.com").concat(jar.getCookies("https://facebook.com")).concat(jar.getCookies("https://www.messenger.com"));
1232
- }
1233
-
1234
- function getData_Path(Obj, Arr, Stt) {
1235
- if (Arr.length === 0 && Obj != undefined) {
1236
- return Obj;
1237
- }
1238
- else if (Obj == undefined) {
1239
- return Stt;
1240
- }
1241
- const head = Arr[0];
1242
- if (head == undefined) {
1243
- return Stt;
1244
- }
1245
- const tail = Arr.slice(1);
1246
- return getData_Path(Obj[head], tail, Stt++);
1247
- }
1248
-
1249
- function setData_Path(obj, path, value) {
1250
- if (!path.length) {
1251
- return obj;
1252
- }
1253
- const currentKey = path[0];
1254
- let currentObj = obj[currentKey];
1255
-
1256
- if (!currentObj) {
1257
- obj[currentKey] = value;
1258
- currentObj = obj[currentKey];
1259
- }
1260
- path.shift();
1261
- if (!path.length) {
1262
- currentObj = value;
1263
- } else {
1264
- currentObj = setData_Path(currentObj, path, value);
1265
- }
1266
-
1267
- return obj;
1268
- }
1269
-
1270
- function getPaths(obj, parentPath = []) {
1271
- let paths = [];
1272
- for (let prop in obj) {
1273
- if (typeof obj[prop] === "object") {
1274
- paths = paths.concat(getPaths(obj[prop], [...parentPath, prop]));
1275
- } else {
1276
- paths.push([...parentPath, prop]);
1277
- }
1278
- }
1279
- return paths;
1280
- }
1281
-
1282
- function cleanHTML(text) {
1283
- text = text.replace(/(<br>)|(<\/?i>)|(<\/?em>)|(<\/?b>)|(!?~)|(&amp;)|(&#039;)|(&lt;)|(&gt;)|(&quot;)/g, (match) => {
1284
- switch (match) {
1285
- case "<br>":
1286
- return "\n";
1287
- case "<i>":
1288
- case "<em>":
1289
- case "</i>":
1290
- case "</em>":
1291
- return "*";
1292
- case "<b>":
1293
- case "</b>":
1294
- return "**";
1295
- case "~!":
1296
- case "!~":
1297
- return "||";
1298
- case "&amp;":
1299
- return "&";
1300
- case "&#039;":
1301
- return "'";
1302
- case "&lt;":
1303
- return "<";
1304
- case "&gt;":
1305
- return ">";
1306
- case "&quot;":
1307
- return '"';
1308
- }
1309
- });
1310
- return text;
1311
- }
1312
-
1313
- function checkLiveCookie(ctx, defaultFuncs) {
1314
- return defaultFuncs.get("https://m.facebook.com/me", ctx.jar).then(function (res) {
1315
- if (res.body.indexOf(ctx.userID) === -1) {
1316
- throw new CustomError({
1317
- message: "Not logged in.",
1318
- error: "Not logged in."
1319
- });
1320
- }
1321
- return true;
1322
- });
1323
- }
1324
-
1325
- function getAccessFromBusiness(jar, Options) {
1326
- return function (res) {
1327
- var html = res ? res.body : null;
1328
- return get('https://business.facebook.com/content_management', jar, null, Options, null, { noRef: true })
1329
- .then(function (res) {
1330
- var token = /"accessToken":"([^.]+)","clientID":/g.exec(res.body)[1];
1331
- return [html, token];
1332
- })
1333
- .catch(function () {
1334
- return [html, null];
1335
- });
1336
- }
1337
- }
1338
-
1339
- module.exports = {
1340
- CustomError,
1341
- cleanHTML,
1342
- isReadableStream: isReadableStream,
1343
- get: get,
1344
- get2: get2,
1345
- post: post,
1346
- postFormData: postFormData,
1347
- generateThreadingID: generateThreadingID,
1348
- generateOfflineThreadingID: generateOfflineThreadingID,
1349
- getGUID: getGUID,
1350
- getFrom: getFrom,
1351
- makeParsable: makeParsable,
1352
- arrToForm: arrToForm,
1353
- getSignatureID: getSignatureID,
1354
- getJar: request.jar,
1355
- generateTimestampRelative: generateTimestampRelative,
1356
- makeDefaults: makeDefaults,
1357
- parseAndCheckLogin: parseAndCheckLogin,
1358
- getData_Path,
1359
- setData_Path,
1360
- getPaths,
1361
- saveCookies,
1362
- getType,
1363
- _formatAttachment,
1364
- formatHistoryMessage,
1365
- formatID,
1366
- formatMessage,
1367
- formatDeltaEvent,
1368
- formatDeltaMessage,
1369
- formatProxyPresence,
1370
- formatPresence,
1371
- formatTyp,
1372
- formatDeltaReadReceipt,
1373
- formatCookie,
1374
- formatThread,
1375
- formatReadReceipt,
1376
- formatRead,
1377
- generatePresence,
1378
- generateAccessiblityCookie,
1379
- formatDate,
1380
- decodeClientPayload,
1381
- getAppState,
1382
- getAdminTextMessageType,
1383
- setProxy,
1384
- checkLiveCookie,
1385
- getAccessFromBusiness,
1386
- getFroms
1387
- };