mariss 0.0.1-security → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mariss might be problematic. Click here for more details.

Files changed (116) hide show
  1. package/.gitattributes +2 -0
  2. package/Extra/Database/index.js +469 -0
  3. package/Extra/ExtraAddons.js +82 -0
  4. package/Extra/ExtraFindUID.js +62 -0
  5. package/Extra/ExtraGetThread.js +340 -0
  6. package/Extra/ExtraScreenShot.js +430 -0
  7. package/Extra/ExtraUptimeRobot.js +38 -0
  8. package/Extra/Html/Classic/script.js +119 -0
  9. package/Extra/Html/Classic/style.css +8 -0
  10. package/Extra/Security/AES_256_GCM/index.js +0 -0
  11. package/Extra/Security/Base/Step_1.js +6 -0
  12. package/Extra/Security/Base/Step_2.js +22 -0
  13. package/Extra/Security/Base/Step_3.js +22 -0
  14. package/Extra/Security/Base/index.js +173 -0
  15. package/Extra/Security/Index.js +5 -0
  16. package/Extra/Security/Step_1.js +6 -0
  17. package/Extra/Security/Step_2.js +22 -0
  18. package/Extra/Security/Step_3.js +22 -0
  19. package/Extra/Src/Change_Environment.js +24 -0
  20. package/Extra/Src/Check_Update.js +67 -0
  21. package/Extra/Src/History.js +115 -0
  22. package/Extra/Src/Instant_Update.js +65 -0
  23. package/Extra/Src/Last-Run.js +65 -0
  24. package/Extra/Src/Premium.js +81 -0
  25. package/Extra/Src/Release_Memory.js +41 -0
  26. package/Extra/Src/Websocket.js +213 -0
  27. package/Extra/Src/image/checkmate.jpg +0 -0
  28. package/Extra/Src/uuid.js +137 -0
  29. package/Func/AcceptAgreement.js +31 -0
  30. package/Func/ClearCache.js +64 -0
  31. package/Func/ReportV1.js +54 -0
  32. package/LICENSE +21 -0
  33. package/Language/index.json +216 -0
  34. package/Main.js +1211 -0
  35. package/README.md +140 -5
  36. package/SECURITY.md +18 -0
  37. package/broadcast.js +40 -0
  38. package/index.js +386 -0
  39. package/logger.js +66 -0
  40. package/package.json +92 -3
  41. package/src/Dev_Horizon_Data.js +125 -0
  42. package/src/Premium.js +25 -0
  43. package/src/Screenshot.js +83 -0
  44. package/src/addExternalModule.js +16 -0
  45. package/src/addUserToGroup.js +79 -0
  46. package/src/changeAdminStatus.js +79 -0
  47. package/src/changeArchivedStatus.js +41 -0
  48. package/src/changeAvt.js +85 -0
  49. package/src/changeBio.js +65 -0
  50. package/src/changeBlockedStatus.js +36 -0
  51. package/src/changeGroupImage.js +106 -0
  52. package/src/changeNickname.js +45 -0
  53. package/src/changeThreadColor.js +62 -0
  54. package/src/changeThreadEmoji.js +42 -0
  55. package/src/createNewGroup.js +70 -0
  56. package/src/createPoll.js +60 -0
  57. package/src/deleteMessage.js +45 -0
  58. package/src/deleteThread.js +43 -0
  59. package/src/forwardAttachment.js +48 -0
  60. package/src/getAccessToken.js +28 -0
  61. package/src/getCurrentUserID.js +7 -0
  62. package/src/getEmojiUrl.js +27 -0
  63. package/src/getFriendsList.js +73 -0
  64. package/src/getMessage.js +80 -0
  65. package/src/getThreadHistory.js +537 -0
  66. package/src/getThreadInfo.js +425 -0
  67. package/src/getThreadList.js +213 -0
  68. package/src/getThreadMain.js +220 -0
  69. package/src/getThreadPictures.js +59 -0
  70. package/src/getUID.js +59 -0
  71. package/src/getUserID.js +62 -0
  72. package/src/getUserInfo.js +113 -0
  73. package/src/getUserInfoMain.js +65 -0
  74. package/src/getUserInfoV2.js +32 -0
  75. package/src/getUserInfoV3.js +63 -0
  76. package/src/getUserInfoV4.js +55 -0
  77. package/src/getUserInfoV5.js +61 -0
  78. package/src/handleFriendRequest.js +46 -0
  79. package/src/handleMessageRequest.js +49 -0
  80. package/src/httpGet.js +49 -0
  81. package/src/httpPost.js +48 -0
  82. package/src/httpPostFormData.js +41 -0
  83. package/src/listenMqtt.js +787 -0
  84. package/src/logout.js +68 -0
  85. package/src/markAsDelivered.js +48 -0
  86. package/src/markAsRead.js +70 -0
  87. package/src/markAsReadAll.js +43 -0
  88. package/src/markAsSeen.js +51 -0
  89. package/src/muteThread.js +47 -0
  90. package/src/removeUserFromGroup.js +49 -0
  91. package/src/resolvePhotoUrl.js +37 -0
  92. package/src/searchForThread.js +43 -0
  93. package/src/sendMessage.js +379 -0
  94. package/src/sendTypingIndicator.js +80 -0
  95. package/src/setMessageReaction.js +109 -0
  96. package/src/setPostReaction.js +102 -0
  97. package/src/setTitle.js +74 -0
  98. package/src/threadColors.js +39 -0
  99. package/src/unfriend.js +43 -0
  100. package/src/unsendMessage.js +40 -0
  101. package/test/Database_Test.js +4 -0
  102. package/test/Db2.js +530 -0
  103. package/test/Horizon_Database/A_README.md +1 -0
  104. package/test/Horizon_Database/Database.db +0 -0
  105. package/test/data/shareAttach.js +146 -0
  106. package/test/data/something.mov +0 -0
  107. package/test/data/test.png +0 -0
  108. package/test/data/test.txt +7 -0
  109. package/test/env/.env +0 -0
  110. package/test/example-config.json +18 -0
  111. package/test/example-db.db +0 -0
  112. package/test/memoryleak.js +18 -0
  113. package/test/test-page.js +140 -0
  114. package/test/test.js +385 -0
  115. package/test/testv2.js +18 -0
  116. package/utils.js +1683 -0
package/utils.js ADDED
@@ -0,0 +1,1683 @@
1
+ // @ts-nocheck
2
+ /* eslint-disable no-undef */
3
+
4
+ /* eslint-disable no-prototype-builtins */
5
+
6
+ "use strict";
7
+ var url = require("url");
8
+ var log = require("npmlog");
9
+ var stream = require("stream");
10
+ var bluebird = require("bluebird");
11
+ var querystring = require("querystring");
12
+ var request = bluebird.promisify(require("request").defaults({ jar: true }));
13
+
14
+ /**
15
+ * @param {any} url
16
+ */
17
+
18
+ function setProxy(url) {
19
+ if (typeof url == undefined) return request = bluebird.promisify(require("request").defaults({ jar: true }));
20
+ return request = bluebird.promisify(require("request").defaults({ jar: true, proxy: url }));
21
+ }
22
+
23
+ /**
24
+ * @param {string | URL} url
25
+ * @param {{ userAgent: any; }} options
26
+ * @param {{ region: any; }} [ctx]
27
+ * @param {undefined} [customHeader]
28
+ */
29
+
30
+ function getHeaders(url, options, ctx, customHeader) {
31
+ var headers = {
32
+ "Content-Type": "application/x-www-form-urlencoded",
33
+ Referer: "https://www.facebook.com/",
34
+ Host: url.replace("https://", "").split("/")[0],
35
+ Origin: "https://www.facebook.com",
36
+ "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"),
37
+ Connection: "keep-alive",
38
+ "sec-fetch-site": 'same-origin',
39
+ "sec-fetch-mode": 'cors'
40
+ };
41
+ if (customHeader) Object.assign(headers, customHeader);
42
+ if (ctx && ctx.region) headers["X-MSGR-Region"] = ctx.region;
43
+
44
+ return headers;
45
+ }
46
+
47
+ /**
48
+ * @param {{ _read: any; _readableState: any; }} obj
49
+ */
50
+
51
+ function isReadableStream(obj) {
52
+ return (
53
+ obj instanceof stream.Stream &&
54
+ (getType(obj._read) === "Function" ||
55
+ getType(obj._read) === "AsyncFunction") &&
56
+ getType(obj._readableState) === "Object"
57
+ );
58
+ }
59
+
60
+ /**
61
+ * @param {any} url
62
+ * @param {any} jar
63
+ * @param {{ [x: string]: any; fb_dtsg?: any; jazoest?: any; hasOwnProperty?: any; }} qs
64
+ * @param {any} options
65
+ * @param {any} ctx
66
+ */
67
+
68
+ function get(url, jar, qs, options, ctx) {
69
+ // I'm still confused about this
70
+ if (getType(qs) === "Object")
71
+ for (var prop in qs)
72
+ if (qs.hasOwnProperty(prop) && getType(qs[prop]) === "Object") qs[prop] = JSON.stringify(qs[prop]);
73
+ var op = {
74
+ headers: getHeaders(url, options, ctx),
75
+ timeout: 60000,
76
+ qs: qs,
77
+ url: url,
78
+ method: "GET",
79
+ jar: jar,
80
+ gzip: true
81
+ };
82
+
83
+ return request(op).then(function(res) {
84
+ return res;
85
+ });
86
+ }
87
+
88
+ function post(url, jar, form, options, ctx, customHeader) {
89
+ var op = {
90
+ headers: getHeaders(url, options),
91
+ timeout: 60000,
92
+ url: url,
93
+ method: "POST",
94
+ form: form,
95
+ jar: jar,
96
+ gzip: true
97
+ };
98
+ return request(op).then(function(res) {
99
+ return res;
100
+ });
101
+ }
102
+
103
+ /**
104
+ * @param {any} url
105
+ * @param {any} jar
106
+ * @param {{ __user: any; __req: string; __rev: any; __a: number;
107
+ // __af: siteData.features,
108
+ fb_dtsg: any; jazoest: any; }} form
109
+ * @param {{ __user: any; __req: string; __rev: any; __a: number;
110
+ // __af: siteData.features,
111
+ fb_dtsg: any; jazoest: any; }} qs
112
+ * @param {any} options
113
+ * @param {any} ctx
114
+ */
115
+
116
+ function postFormData(url, jar, form, qs, options, ctx) {
117
+ var headers = getHeaders(url, options, ctx);
118
+ headers["Content-Type"] = "multipart/form-data";
119
+ var op = {
120
+ headers: headers,
121
+ timeout: 60000,
122
+ url: url,
123
+ method: "POST",
124
+ formData: form,
125
+ qs: qs,
126
+ jar: jar,
127
+ gzip: true
128
+ };
129
+
130
+ return request(op).then(function(res) {
131
+ return res;
132
+ });
133
+ }
134
+
135
+ /**
136
+ * @param {string | number | any[]} val
137
+ * @param {number} [len]
138
+ */
139
+
140
+ function padZeros(val, len) {
141
+ val = String(val);
142
+ len = len || 2;
143
+ while (val.length < len) val = "0" + val;
144
+ return val;
145
+ }
146
+
147
+ /**
148
+ * @param {any} clientID
149
+ */
150
+
151
+ function generateThreadingID(clientID) {
152
+ var k = Date.now();
153
+ var l = Math.floor(Math.random() * 4294967295);
154
+ var m = clientID;
155
+ return "<" + k + ":" + l + "-" + m + "@mail.projektitan.com>";
156
+ }
157
+
158
+ /**
159
+ * @param {string | any[]} data
160
+ */
161
+
162
+ function binaryToDecimal(data) {
163
+ var ret = "";
164
+ while (data !== "0") {
165
+ var end = 0;
166
+ var fullName = "";
167
+ var i = 0;
168
+ for (; i < data.length; i++) {
169
+ end = 2 * end + parseInt(data[i], 10);
170
+ if (end >= 10) {
171
+ fullName += "1";
172
+ end -= 10;
173
+ } else fullName += "0";
174
+ }
175
+ ret = end.toString() + ret;
176
+ data = fullName.slice(fullName.indexOf("1"));
177
+ }
178
+ return ret;
179
+ }
180
+
181
+ function generateOfflineThreadingID() {
182
+ var ret = Date.now();
183
+ var value = Math.floor(Math.random() * 4294967295);
184
+ var str = ("0000000000000000000000" + value.toString(2)).slice(-22);
185
+ var msgs = ret.toString(2) + str;
186
+ return binaryToDecimal(msgs);
187
+ }
188
+
189
+ var h;
190
+ var i = {};
191
+ var j = {
192
+ _: "%",
193
+ A: "%2",
194
+ B: "000",
195
+ C: "%7d",
196
+ D: "%7b%22",
197
+ E: "%2c%22",
198
+ F: "%22%3a",
199
+ G: "%2c%22ut%22%3a1",
200
+ H: "%2c%22bls%22%3a",
201
+ I: "%2c%22n%22%3a%22%",
202
+ J: "%22%3a%7b%22i%22%3a0%7d",
203
+ K: "%2c%22pt%22%3a0%2c%22vis%22%3a",
204
+ L: "%2c%22ch%22%3a%7b%22h%22%3a%22",
205
+ M: "%7b%22v%22%3a2%2c%22time%22%3a1",
206
+ N: ".channel%22%2c%22sub%22%3a%5b",
207
+ O: "%2c%22sb%22%3a1%2c%22t%22%3a%5b",
208
+ P: "%2c%22ud%22%3a100%2c%22lc%22%3a0",
209
+ Q: "%5d%2c%22f%22%3anull%2c%22uct%22%3a",
210
+ R: ".channel%22%2c%22sub%22%3a%5b1%5d",
211
+ S: "%22%2c%22m%22%3a0%7d%2c%7b%22i%22%3a",
212
+ T: "%2c%22blc%22%3a1%2c%22snd%22%3a1%2c%22ct%22%3a",
213
+ U: "%2c%22blc%22%3a0%2c%22snd%22%3a1%2c%22ct%22%3a",
214
+ V: "%2c%22blc%22%3a0%2c%22snd%22%3a0%2c%22ct%22%3a",
215
+ W: "%2c%22s%22%3a0%2c%22blo%22%3a0%7d%2c%22bl%22%3a%7b%22ac%22%3a",
216
+ X: "%2c%22ri%22%3a0%7d%2c%22state%22%3a%7b%22p%22%3a0%2c%22ut%22%3a1",
217
+ 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",
218
+ 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"
219
+ };
220
+ (function() {
221
+ var l = [];
222
+ for (var m in j) {
223
+ i[j[m]] = m;
224
+ l.push(j[m]);
225
+ }
226
+ l.reverse();
227
+ h = new RegExp(l.join("|"), "g");
228
+ })();
229
+
230
+ /**
231
+ * @param {string | number | boolean} str
232
+ */
233
+
234
+ function presenceEncode(str) {
235
+ return encodeURIComponent(str)
236
+ .replace(/([_A-Z])|%../g, function(m, n) {
237
+ return n ? "%" + n.charCodeAt(0).toString(16) : m;
238
+ })
239
+ .toLowerCase()
240
+ .replace(h, function(m) {
241
+ return i[m];
242
+ });
243
+ }
244
+
245
+ // eslint-disable-next-line no-unused-vars
246
+ /**
247
+ * @param {string} str
248
+ */
249
+
250
+ function presenceDecode(str) {
251
+ return decodeURIComponent(
252
+ str.replace(/[_A-Z]/g, function(/** @type {string | number} */m) {
253
+ return j[m];
254
+ })
255
+ );
256
+ }
257
+
258
+ /**
259
+ * @param {string} userID
260
+ */
261
+
262
+ function generatePresence(userID) {
263
+ var time = Date.now();
264
+ return (
265
+ "E" +
266
+ presenceEncode(
267
+ JSON.stringify({
268
+ v: 3,
269
+ time: parseInt(time / 1000, 10),
270
+ user: userID,
271
+ state: {
272
+ ut: 0,
273
+ t2: [],
274
+ lm2: null,
275
+ uct2: time,
276
+ tr: null,
277
+ tw: Math.floor(Math.random() * 4294967295) + 1,
278
+ at: time
279
+ },
280
+ ch: {
281
+ ["p_" + userID]: 0
282
+ }
283
+ })
284
+ )
285
+ );
286
+ }
287
+
288
+ function generateAccessiblityCookie() {
289
+ var time = Date.now();
290
+ return encodeURIComponent(
291
+ JSON.stringify({
292
+ sr: 0,
293
+ "sr-ts": time,
294
+ jk: 0,
295
+ "jk-ts": time,
296
+ kb: 0,
297
+ "kb-ts": time,
298
+ hcm: 0,
299
+ "hcm-ts": time
300
+ })
301
+ );
302
+ }
303
+
304
+ function getGUID() {
305
+ /** @type {number} */
306
+
307
+ var sectionLength = Date.now();
308
+ /** @type {string} */
309
+
310
+ var id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
311
+ /** @type {number} */
312
+
313
+ var r = Math.floor((sectionLength + Math.random() * 16) % 16);
314
+ /** @type {number} */
315
+
316
+ sectionLength = Math.floor(sectionLength / 16);
317
+ /** @type {string} */
318
+
319
+ var _guid = (c == "x" ? r : (r & 7) | 8).toString(16);
320
+ return _guid;
321
+ });
322
+ return id;
323
+ }
324
+
325
+ /**
326
+ * @param {{ mercury: any; blob_attachment: any; attach_type: any; sticker_attachment: any; extensible_attachment: { story_attachment: { target: { __typename: string; }; }; }; metadata: { stickerID: { toString: () => any; }; packID: { toString: () => any; }; spriteURI: any; spriteURI2x: any; width: any; height: any; frameCount: any; frameRate: any; framesPerRow: any; framesPerCol: any; fbid: { toString: () => any; }; url: any; dimensions: { split: (arg0: string) => any[]; width: any; height: any; }; duration: any; }; url: any; name: any; fileName: any; thumbnail_url: any; preview_url: any; preview_width: any; preview_height: any; large_preview_url: any; large_preview_width: any; large_preview_height: any; share: { share_id: { toString: () => any; }; title: any; description: any; source: any; media: { image: any; image_size: { width: any; height: any; }; playable: any; duration: any; animated_image_size: any; }; subattachments: any; uri: any; target: any; style_list: any; }; }} attachment1
327
+ * @param {{ caption?: any; description?: any; id: any; is_malicious?: any; mime_type?: any; file_size?: any; filename?: any; image_data: any; href?: any; }} [attachment2]
328
+ */
329
+
330
+ function _formatAttachment(attachment1, attachment2) {
331
+ // TODO: THIS IS REALLY BAD
332
+ // This is an attempt at fixing Facebook's inconsistencies. Sometimes they give us
333
+ // two attachment objects, but sometimes only one. They each contain part of the
334
+ // data that you'd want so we merge them for convenience.
335
+ // Instead of having a bunch of if statements guarding every access to image_data,
336
+ // we set it to empty object and use the fact that it'll return undefined.
337
+
338
+ attachment2 = attachment2 || { id: "", image_data: {} };
339
+ attachment1 = attachment1.mercury ? attachment1.mercury : attachment1;
340
+ var blob = attachment1.blob_attachment;
341
+ var type =
342
+ blob && blob.__typename ? blob.__typename : attachment1.attach_type;
343
+ if (!type && attachment1.sticker_attachment) {
344
+ type = "StickerAttachment";
345
+ blob = attachment1.sticker_attachment;
346
+ } else if (!type && attachment1.extensible_attachment) {
347
+ if (
348
+ attachment1.extensible_attachment.story_attachment &&
349
+ attachment1.extensible_attachment.story_attachment.target &&
350
+ attachment1.extensible_attachment.story_attachment.target.__typename &&
351
+ attachment1.extensible_attachment.story_attachment.target.__typename === "MessageLocation"
352
+ ) type = "MessageLocation";
353
+ else type = "ExtensibleAttachment";
354
+
355
+ blob = attachment1.extensible_attachment;
356
+ }
357
+ // TODO: Determine whether "sticker", "photo", "file" etc are still used
358
+ // KEEP IN SYNC WITH getThreadHistory
359
+ switch (type) {
360
+ case "sticker":
361
+ return {
362
+ type: "sticker",
363
+ ID: attachment1.metadata.stickerID.toString(),
364
+ url: attachment1.url,
365
+
366
+ packID: attachment1.metadata.packID.toString(),
367
+ spriteUrl: attachment1.metadata.spriteURI,
368
+ spriteUrl2x: attachment1.metadata.spriteURI2x,
369
+ width: attachment1.metadata.width,
370
+ height: attachment1.metadata.height,
371
+
372
+ caption: attachment2.caption,
373
+ description: attachment2.description,
374
+
375
+ frameCount: attachment1.metadata.frameCount,
376
+ frameRate: attachment1.metadata.frameRate,
377
+ framesPerRow: attachment1.metadata.framesPerRow,
378
+ framesPerCol: attachment1.metadata.framesPerCol,
379
+
380
+ stickerID: attachment1.metadata.stickerID.toString(), // @Legacy
381
+ spriteURI: attachment1.metadata.spriteURI, // @Legacy
382
+ spriteURI2x: attachment1.metadata.spriteURI2x // @Legacy
383
+ };
384
+ case "file":
385
+ return {
386
+ type: "file",
387
+ filename: attachment1.name,
388
+ ID: attachment2.id.toString(),
389
+ url: attachment1.url,
390
+
391
+ isMalicious: attachment2.is_malicious,
392
+ contentType: attachment2.mime_type,
393
+
394
+ name: attachment1.name, // @Legacy
395
+ mimeType: attachment2.mime_type, // @Legacy
396
+ fileSize: attachment2.file_size // @Legacy
397
+ };
398
+ case "photo":
399
+ return {
400
+ type: "photo",
401
+ ID: attachment1.metadata.fbid.toString(),
402
+ filename: attachment1.fileName,
403
+ thumbnailUrl: attachment1.thumbnail_url,
404
+
405
+ previewUrl: attachment1.preview_url,
406
+ previewWidth: attachment1.preview_width,
407
+ previewHeight: attachment1.preview_height,
408
+
409
+ largePreviewUrl: attachment1.large_preview_url,
410
+ largePreviewWidth: attachment1.large_preview_width,
411
+ largePreviewHeight: attachment1.large_preview_height,
412
+
413
+ url: attachment1.metadata.url, // @Legacy
414
+ width: attachment1.metadata.dimensions.split(",")[0], // @Legacy
415
+ height: attachment1.metadata.dimensions.split(",")[1], // @Legacy
416
+ name: attachment1.fileName // @Legacy
417
+ };
418
+ case "animated_image":
419
+ return {
420
+ type: "animated_image",
421
+ ID: attachment2.id.toString(),
422
+ filename: attachment2.filename,
423
+
424
+ previewUrl: attachment1.preview_url,
425
+ previewWidth: attachment1.preview_width,
426
+ previewHeight: attachment1.preview_height,
427
+
428
+ url: attachment2.image_data.url,
429
+ width: attachment2.image_data.width,
430
+ height: attachment2.image_data.height,
431
+
432
+ name: attachment1.name, // @Legacy
433
+ facebookUrl: attachment1.url, // @Legacy
434
+ thumbnailUrl: attachment1.thumbnail_url, // @Legacy
435
+ mimeType: attachment2.mime_type, // @Legacy
436
+ rawGifImage: attachment2.image_data.raw_gif_image, // @Legacy
437
+ rawWebpImage: attachment2.image_data.raw_webp_image, // @Legacy
438
+ animatedGifUrl: attachment2.image_data.animated_gif_url, // @Legacy
439
+ animatedGifPreviewUrl: attachment2.image_data.animated_gif_preview_url, // @Legacy
440
+ animatedWebpUrl: attachment2.image_data.animated_webp_url, // @Legacy
441
+ animatedWebpPreviewUrl: attachment2.image_data.animated_webp_preview_url // @Legacy
442
+ };
443
+ case "share":
444
+ return {
445
+ type: "share",
446
+ ID: attachment1.share.share_id.toString(),
447
+ url: attachment2.href,
448
+
449
+ title: attachment1.share.title,
450
+ description: attachment1.share.description,
451
+ source: attachment1.share.source,
452
+
453
+ image: attachment1.share.media.image,
454
+ width: attachment1.share.media.image_size.width,
455
+ height: attachment1.share.media.image_size.height,
456
+ playable: attachment1.share.media.playable,
457
+ duration: attachment1.share.media.duration,
458
+
459
+ subattachments: attachment1.share.subattachments,
460
+ properties: {},
461
+
462
+ animatedImageSize: attachment1.share.media.animated_image_size, // @Legacy
463
+ facebookUrl: attachment1.share.uri, // @Legacy
464
+ target: attachment1.share.target, // @Legacy
465
+ styleList: attachment1.share.style_list // @Legacy
466
+ };
467
+ case "video":
468
+ return {
469
+ type: "video",
470
+ ID: attachment1.metadata.fbid.toString(),
471
+ filename: attachment1.name,
472
+
473
+ previewUrl: attachment1.preview_url,
474
+ previewWidth: attachment1.preview_width,
475
+ previewHeight: attachment1.preview_height,
476
+
477
+ url: attachment1.url,
478
+ width: attachment1.metadata.dimensions.width,
479
+ height: attachment1.metadata.dimensions.height,
480
+
481
+ duration: attachment1.metadata.duration,
482
+ videoType: "unknown",
483
+
484
+ thumbnailUrl: attachment1.thumbnail_url // @Legacy
485
+ };
486
+ case "error":
487
+ return {
488
+ type: "error",
489
+
490
+ // Save error attachments because we're unsure of their format,
491
+ // and whether there are cases they contain something useful for debugging.
492
+ attachment1: attachment1,
493
+ attachment2: attachment2
494
+ };
495
+ case "MessageImage":
496
+ return {
497
+ type: "photo",
498
+ ID: blob.legacy_attachment_id,
499
+ filename: blob.filename,
500
+ thumbnailUrl: blob.thumbnail.uri,
501
+
502
+ previewUrl: blob.preview.uri,
503
+ previewWidth: blob.preview.width,
504
+ previewHeight: blob.preview.height,
505
+
506
+ largePreviewUrl: blob.large_preview.uri,
507
+ largePreviewWidth: blob.large_preview.width,
508
+ largePreviewHeight: blob.large_preview.height,
509
+
510
+ url: blob.large_preview.uri, // @Legacy
511
+ width: blob.original_dimensions.x, // @Legacy
512
+ height: blob.original_dimensions.y, // @Legacy
513
+ name: blob.filename // @Legacy
514
+ };
515
+ case "MessageAnimatedImage":
516
+ return {
517
+ type: "animated_image",
518
+ ID: blob.legacy_attachment_id,
519
+ filename: blob.filename,
520
+
521
+ previewUrl: blob.preview_image.uri,
522
+ previewWidth: blob.preview_image.width,
523
+ previewHeight: blob.preview_image.height,
524
+
525
+ url: blob.animated_image.uri,
526
+ width: blob.animated_image.width,
527
+ height: blob.animated_image.height,
528
+
529
+ thumbnailUrl: blob.preview_image.uri, // @Legacy
530
+ name: blob.filename, // @Legacy
531
+ facebookUrl: blob.animated_image.uri, // @Legacy
532
+ rawGifImage: blob.animated_image.uri, // @Legacy
533
+ animatedGifUrl: blob.animated_image.uri, // @Legacy
534
+ animatedGifPreviewUrl: blob.preview_image.uri, // @Legacy
535
+ animatedWebpUrl: blob.animated_image.uri, // @Legacy
536
+ animatedWebpPreviewUrl: blob.preview_image.uri // @Legacy
537
+ };
538
+ case "MessageVideo":
539
+ return {
540
+ type: "video",
541
+ filename: blob.filename,
542
+ ID: blob.legacy_attachment_id,
543
+
544
+ previewUrl: blob.large_image.uri,
545
+ previewWidth: blob.large_image.width,
546
+ previewHeight: blob.large_image.height,
547
+
548
+ url: blob.playable_url,
549
+ width: blob.original_dimensions.x,
550
+ height: blob.original_dimensions.y,
551
+
552
+ duration: blob.playable_duration_in_ms,
553
+ videoType: blob.video_type.toLowerCase(),
554
+
555
+ thumbnailUrl: blob.large_image.uri // @Legacy
556
+ };
557
+ case "MessageAudio":
558
+ return {
559
+ type: "audio",
560
+ filename: blob.filename,
561
+ ID: blob.url_shimhash,
562
+
563
+ audioType: blob.audio_type,
564
+ duration: blob.playable_duration_in_ms,
565
+ url: blob.playable_url,
566
+
567
+ isVoiceMail: blob.is_voicemail
568
+ };
569
+ case "StickerAttachment":
570
+ return {
571
+ type: "sticker",
572
+ ID: blob.id,
573
+ url: blob.url,
574
+
575
+ packID: blob.pack ? blob.pack.id : null,
576
+ spriteUrl: blob.sprite_image,
577
+ spriteUrl2x: blob.sprite_image_2x,
578
+ width: blob.width,
579
+ height: blob.height,
580
+
581
+ caption: blob.label,
582
+ description: blob.label,
583
+
584
+ frameCount: blob.frame_count,
585
+ frameRate: blob.frame_rate,
586
+ framesPerRow: blob.frames_per_row,
587
+ framesPerCol: blob.frames_per_column,
588
+
589
+ stickerID: blob.id, // @Legacy
590
+ spriteURI: blob.sprite_image, // @Legacy
591
+ spriteURI2x: blob.sprite_image_2x // @Legacy
592
+ };
593
+ case "MessageLocation":
594
+ var urlAttach = blob.story_attachment.url;
595
+ var mediaAttach = blob.story_attachment.media;
596
+
597
+ var u = querystring.parse(url.parse(urlAttach).query).u;
598
+ var where1 = querystring.parse(url.parse(u).query).where1;
599
+ var address = where1.split(", ");
600
+
601
+ var latitude;
602
+ var longitude;
603
+
604
+ try {
605
+ latitude = Number.parseFloat(address[0]);
606
+ longitude = Number.parseFloat(address[1]);
607
+ } catch (err) {
608
+ /* empty */
609
+
610
+ }
611
+
612
+ var imageUrl;
613
+ var width;
614
+ var height;
615
+
616
+ if (mediaAttach && mediaAttach.image) {
617
+ imageUrl = mediaAttach.image.uri;
618
+ width = mediaAttach.image.width;
619
+ height = mediaAttach.image.height;
620
+ }
621
+
622
+ return {
623
+ type: "location",
624
+ ID: blob.legacy_attachment_id,
625
+ latitude: latitude,
626
+ longitude: longitude,
627
+ image: imageUrl,
628
+ width: width,
629
+ height: height,
630
+ url: u || urlAttach,
631
+ address: where1,
632
+
633
+ facebookUrl: blob.story_attachment.url, // @Legacy
634
+ target: blob.story_attachment.target, // @Legacy
635
+ styleList: blob.story_attachment.style_list // @Legacy
636
+ };
637
+ case "ExtensibleAttachment":
638
+ return {
639
+ type: "share",
640
+ ID: blob.legacy_attachment_id,
641
+ url: blob.story_attachment.url,
642
+
643
+ title: blob.story_attachment.title_with_entities.text,
644
+ description: blob.story_attachment.description &&
645
+ blob.story_attachment.description.text,
646
+ source: blob.story_attachment.source ? blob.story_attachment.source.text : null,
647
+
648
+ image: blob.story_attachment.media &&
649
+ blob.story_attachment.media.image &&
650
+ blob.story_attachment.media.image.uri,
651
+ width: blob.story_attachment.media &&
652
+ blob.story_attachment.media.image &&
653
+ blob.story_attachment.media.image.width,
654
+ height: blob.story_attachment.media &&
655
+ blob.story_attachment.media.image &&
656
+ blob.story_attachment.media.image.height,
657
+ playable: blob.story_attachment.media &&
658
+ blob.story_attachment.media.is_playable,
659
+ duration: blob.story_attachment.media &&
660
+ blob.story_attachment.media.playable_duration_in_ms,
661
+ playableUrl: blob.story_attachment.media == null ? null : blob.story_attachment.media.playable_url,
662
+
663
+ subattachments: blob.story_attachment.subattachments,
664
+ properties: blob.story_attachment.properties.reduce(function(/** @type {{ [x: string]: any; }} */obj, /** @type {{ key: string | number; value: { text: any; }; }} */cur) {
665
+ obj[cur.key] = cur.value.text;
666
+ return obj;
667
+ }, {}),
668
+
669
+ facebookUrl: blob.story_attachment.url, // @Legacy
670
+ target: blob.story_attachment.target, // @Legacy
671
+ styleList: blob.story_attachment.style_list // @Legacy
672
+ };
673
+ case "MessageFile":
674
+ return {
675
+ type: "file",
676
+ filename: blob.filename,
677
+ ID: blob.message_file_fbid,
678
+
679
+ url: blob.url,
680
+ isMalicious: blob.is_malicious,
681
+ contentType: blob.content_type,
682
+
683
+ name: blob.filename,
684
+ mimeType: "",
685
+ fileSize: -1
686
+ };
687
+ default:
688
+ throw new Error(
689
+ "unrecognized attach_file of type " +
690
+ type +
691
+ "`" +
692
+ JSON.stringify(attachment1, null, 4) +
693
+ " attachment2: " +
694
+ JSON.stringify(attachment2, null, 4) +
695
+ "`"
696
+ );
697
+ }
698
+ }
699
+
700
+ /**
701
+ * @param {any[]} attachments
702
+ * @param {{ [x: string]: string | number; }} attachmentIds
703
+ * @param {{ [x: string]: any; }} attachmentMap
704
+ * @param {any} shareMap
705
+ */
706
+
707
+ function formatAttachment(attachments, attachmentIds, attachmentMap, shareMap) {
708
+ attachmentMap = shareMap || attachmentMap;
709
+ return attachments ?
710
+ attachments.map(function(/** @type {any} */val, /** @type {string | number} */i) {
711
+ if (!attachmentMap ||
712
+ !attachmentIds ||
713
+ !attachmentMap[attachmentIds[i]]
714
+ ) {
715
+ return _formatAttachment(val);
716
+ }
717
+ return _formatAttachment(val, attachmentMap[attachmentIds[i]]);
718
+ }) : [];
719
+ }
720
+
721
+ /**
722
+ * @param {{ delta: { messageMetadata: any; data: { prng: string; }; body: string; attachments: any; participants: any; }; }} m
723
+ */
724
+
725
+ function formatDeltaMessage(m) {
726
+ var md = m.delta.messageMetadata;
727
+ var mdata =
728
+ m.delta.data === undefined ? [] :
729
+ m.delta.data.prng === undefined ? [] :
730
+ JSON.parse(m.delta.data.prng);
731
+ var m_id = mdata.map((/** @type {{ i: any; }} */u) => u.i);
732
+ var m_offset = mdata.map((/** @type {{ o: any; }} */u) => u.o);
733
+ var m_length = mdata.map((/** @type {{ l: any; }} */u) => u.l);
734
+ var mentions = {};
735
+ var body = m.delta.body || "";
736
+ var args = body == "" ? [] : body.trim().split(/\s+/);
737
+ for (var i = 0; i < m_id.length; i++) mentions[m_id[i]] = m.delta.body.substring(m_offset[i], m_offset[i] + m_length[i]);
738
+
739
+ return {
740
+ type: "message",
741
+ senderID: formatID(md.actorFbId.toString()),
742
+ threadID: formatID((md.threadKey.threadFbId || md.threadKey.otherUserFbId).toString()),
743
+ messageID: md.messageId,
744
+ args: args,
745
+ body: body,
746
+ attachments: (m.delta.attachments || []).map((/** @type {any} */v) => _formatAttachment(v)),
747
+ mentions: mentions,
748
+ timestamp: md.timestamp,
749
+ isGroup: !!md.threadKey.threadFbId,
750
+ participantIDs: m.delta.participants || []
751
+ };
752
+ }
753
+
754
+ /**
755
+ * @param {string} id
756
+ */
757
+
758
+ function formatID(id) {
759
+ if (id != undefined && id != null) return id.replace(/(fb)?id[:.]/, "");
760
+ else return id;
761
+ }
762
+
763
+ /**
764
+ * @param {{ message: any; type: string; realtime_viewer_fbid: { toString: () => any; }; }} m
765
+ */
766
+
767
+ function formatMessage(m) {
768
+ var originalMessage = m.message ? m.message : m;
769
+ var obj = {
770
+ type: "message",
771
+ senderName: originalMessage.sender_name,
772
+ senderID: formatID(originalMessage.sender_fbid.toString()),
773
+ participantNames: originalMessage.group_thread_info ? originalMessage.group_thread_info.participant_names : [originalMessage.sender_name.split(" ")[0]],
774
+ participantIDs: originalMessage.group_thread_info ?
775
+ originalMessage.group_thread_info.participant_ids.map(function(/** @type {{ toString: () => any; }} */v) {
776
+ return formatID(v.toString());
777
+ }) : [formatID(originalMessage.sender_fbid)],
778
+ body: originalMessage.body || "",
779
+ threadID: formatID((originalMessage.thread_fbid || originalMessage.other_user_fbid).toString()),
780
+ threadName: originalMessage.group_thread_info ? originalMessage.group_thread_info.name : originalMessage.sender_name,
781
+ location: originalMessage.coordinates ? originalMessage.coordinates : null,
782
+ messageID: originalMessage.mid ? originalMessage.mid.toString() : originalMessage.message_id,
783
+ attachments: formatAttachment(
784
+ originalMessage.attachments,
785
+ originalMessage.attachmentIds,
786
+ originalMessage.attachment_map,
787
+ originalMessage.share_map
788
+ ),
789
+ timestamp: originalMessage.timestamp,
790
+ timestampAbsolute: originalMessage.timestamp_absolute,
791
+ timestampRelative: originalMessage.timestamp_relative,
792
+ timestampDatetime: originalMessage.timestamp_datetime,
793
+ tags: originalMessage.tags,
794
+ reactions: originalMessage.reactions ? originalMessage.reactions : [],
795
+ isUnread: originalMessage.is_unread
796
+ };
797
+
798
+ if (m.type === "pages_messaging") obj.pageID = m.realtime_viewer_fbid.toString();
799
+ obj.isGroup = obj.participantIDs.length > 2;
800
+
801
+ return obj;
802
+ }
803
+
804
+ /**
805
+ * @param {{ message: any; }} m
806
+ */
807
+
808
+ function formatEvent(m) {
809
+ var originalMessage = m.message ? m.message : m;
810
+ var logMessageType = originalMessage.log_message_type;
811
+ var logMessageData;
812
+ if (logMessageType === "log:generic-admin-text") {
813
+ logMessageData = originalMessage.log_message_data.untypedData;
814
+ logMessageType = getAdminTextMessageType(originalMessage.log_message_data.message_type);
815
+ } else logMessageData = originalMessage.log_message_data;
816
+
817
+ return Object.assign(formatMessage(originalMessage), {
818
+ type: "event",
819
+ logMessageType: logMessageType,
820
+ logMessageData: logMessageData,
821
+ logMessageBody: originalMessage.log_message_body
822
+ });
823
+ }
824
+
825
+ /**
826
+ * @param {{ action_type: any; }} m
827
+ */
828
+
829
+ function formatHistoryMessage(m) {
830
+ switch (m.action_type) {
831
+ case "ma-type:log-message":
832
+ return formatEvent(m);
833
+ default:
834
+ return formatMessage(m);
835
+ }
836
+ }
837
+
838
+ // Get a more readable message type for AdminTextMessages
839
+ /**
840
+ * @param {{ type: any; }} m
841
+ */
842
+
843
+ function getAdminTextMessageType(m) {
844
+ switch (m.type) {
845
+ case "joinable_group_link_mode_change":
846
+ return "log:link-status";
847
+ case "magic_words":
848
+ return "log:magic-words";
849
+ case "change_thread_theme":
850
+ return "log:thread-color";
851
+ case "change_thread_icon":
852
+ return "log:thread-icon";
853
+ case "change_thread_nickname":
854
+ return "log:user-nickname";
855
+ case "change_thread_admins":
856
+ return "log:thread-admins";
857
+ case "group_poll":
858
+ return "log:thread-poll";
859
+ case "change_thread_approval_mode":
860
+ return "log:thread-approval-mode";
861
+ case "messenger_call_log":
862
+ case "participant_joined_group_call":
863
+ return "log:thread-call";
864
+ case "pin_messages_v2":
865
+ return "log:thread-pinned";
866
+ }
867
+ }
868
+
869
+ /**
870
+ * @param {string} name
871
+ */
872
+
873
+ function getGenderByPhysicalMethod(name) {
874
+ var GirlName = ["LAN", "HÂN", "LINH", "MAI", "HOA", "THU", "BĂNG", "MỸ", "CHÂU", "THẢO", "THOA", "MẪN", "THÙY", "THỦY", "NGA", "NGÂN", "NGHI", "THƯ", "NGỌC", "BÍCH", "VÂN", "DIỆP", "CHI", "TIÊN", "XUÂN", "GIANG", "NHUNG", "DUNG", "NHƯ", "YẾN", "QUYÊN", "YẾN", "TƯỜNG", "VY", "PHƯƠNG", "LIÊN", "LAN", "HÀ", "MAI", "ĐAN", "HẠ", "QUYÊN", "LY", "HÒA", "OANH", "HƯƠNG", "HẰNG", "QUỲNH", "HẠNH", "NHIÊN", "NHẠN"];
875
+
876
+ var BoyName = ["HƯNG", "HUY", "KHẢI", "KHANG", "KHOA", "KHÔI", "KIÊN", "KIỆT", "LONG", "MINH", "ÂN", "BẢO", "BÌNH", "CƯỜNG", "ĐẠT", "ĐỨC", "DŨNG", "DUY", "HOÀNG", "HÙNG", "HƯNG", "NGHĨA", "NGUYÊN", "THẮNG", "THIỆN", "THỊNH", "TÒA", "TRIẾT", "TRUNG", "TRƯỜNG", "TUẤN", "NHÂN", "VŨ", "VINH", "PHONG", "PHÚC", "QUÂN", "QUANG", "SƠN", "TÀI", "THẮNG", "ĐĂNG", "VĂN", "VĨ", "QUANG", "MẠNH"];
877
+
878
+ var OtherName = ["ANH", "THANH", "TÂM", "DƯƠNG", "AN", "LÂM", "MIÊN", "TÚ", "LÂM", "BẰNG", "KHÁNH", "NHẬT", "VỸ", ".",",","/","%", "&","*","-","+"];
879
+
880
+ try {
881
+ var NameArray = name.split(" ");
882
+ name = NameArray[NameArray.length - 1];
883
+ var Name;
884
+ if (name == " " || name == null) return "UNKNOWN";
885
+ switch (GirlName.includes(name.toUpperCase())) {
886
+ case true: {
887
+ if (!OtherName.includes(name.toUpperCase()) && !BoyName.includes(name.toUpperCase())) Name = "FEMALE";
888
+ else Name = ['FEMALE','MALE'][Math.floor(Math.random() * 2)]; // just temp 🌚
889
+ }
890
+ break;
891
+ case false: {
892
+ if (!OtherName.includes(name.toUpperCase()) && !GirlName.includes(name.toUpperCase())) Name = "MALE";
893
+ else Name = ['FEMALE','MALE'][Math.floor(Math.random() * 2)]; // just temp 🌚
894
+ }
895
+ break;
896
+ }
897
+ }
898
+ catch (e) {
899
+ return "UNKNOWN";
900
+ }
901
+ return Name || "UNKNOWN";
902
+ }
903
+
904
+ /**
905
+ * @param {{ [x: string]: { [x: string]: { [x: string]: any; }; }; class: any; untypedData: any; name: any; addedParticipants: any; leftParticipantFbId: any; messageMetadata: { threadKey: { threadFbId: any; otherUserFbId: any; }; adminText: any; actorFbId: any; }; participants: any; }} m
906
+ */
907
+
908
+ function formatDeltaEvent(m) {
909
+ var { updateData,getData,hasData } = require('./Extra/ExtraGetThread');
910
+ var logMessageType;
911
+ var logMessageData;
912
+
913
+ switch (m.class) {
914
+ case "AdminTextMessage":
915
+ logMessageType = getAdminTextMessageType(m);
916
+ logMessageData = m.untypedData;
917
+ break;
918
+ case "ThreadName":
919
+ logMessageType = "log:thread-name";
920
+ logMessageData = { name: m.name };
921
+ break;
922
+ case "ParticipantsAddedToGroupThread":
923
+ logMessageType = "log:subscribe";
924
+ logMessageData = { addedParticipants: m.addedParticipants };
925
+ break;
926
+ case "ParticipantLeftGroupThread":
927
+ logMessageType = "log:unsubscribe";
928
+ logMessageData = { leftParticipantFbId: m.leftParticipantFbId };
929
+ break;
930
+ case "UserLocation": {
931
+ logMessageType = "log:user-location";
932
+ logMessageData = {
933
+ Image: m.attachments[0].mercury.extensible_attachment.story_attachment.media.image,
934
+ Location: m.attachments[0].mercury.extensible_attachment.story_attachment.target.location_title,
935
+ coordinates: m.attachments[0].mercury.extensible_attachment.story_attachment.target.coordinate,
936
+ url: m.attachments[0].mercury.extensible_attachment.story_attachment.url
937
+ };
938
+ }
939
+ }
940
+ switch (hasData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()))) {
941
+ case true: {
942
+ switch (logMessageType) {
943
+ case "log:thread-color": {
944
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
945
+ x.emoji = (logMessageData.theme_emoji || x.emoji);
946
+ x.color = (logMessageData['theme_color'] || x.color);
947
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
948
+ }
949
+ break;
950
+ case "log:thread-icon": {
951
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
952
+ x.emoji = (logMessageData['thread_icon'] || x.emoji);
953
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
954
+ }
955
+ break;
956
+ case "log:user-nickname": {
957
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
958
+ x.nicknames[logMessageData.participant_id] = (logMessageData.nickname.length == 0 ? x.userInfo.find(i => i.id == String(logMessageData.participant_id)).name : logMessageData.nickname);
959
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
960
+ }
961
+ break;
962
+ case "log:thread-admins": {
963
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
964
+ switch (logMessageData.ADMIN_EVENT) {
965
+ case "add_admin": {
966
+ x.adminIDs.push({ id: logMessageData.TARGET_ID });
967
+ }
968
+ break;
969
+ case "remove_admin": {
970
+ x.adminIDs = x.adminIDs.filter(item => item.id != logMessageData.TARGET_ID);
971
+ }
972
+ break;
973
+ }
974
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
975
+ }
976
+ break;
977
+ case "log:thread-approval-mode": {
978
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
979
+ if (x.approvalMode == true) {
980
+ x.approvalMode = false;
981
+ }
982
+ else {
983
+ x.approvalMode = true;
984
+ }
985
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
986
+ }
987
+ break;
988
+ case "log:thread-name": {
989
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
990
+ x.threadName = (logMessageData.name || formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
991
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
992
+ }
993
+ break;
994
+ case "log:subscribe": {
995
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
996
+ for (let o of logMessageData.addedParticipants) {
997
+ if (x.userInfo.some(i => i.id == o.userFbId)) continue;
998
+ else {
999
+ x.userInfo.push({
1000
+ id: o.userFbId,
1001
+ name: o.fullName,
1002
+ gender: getGenderByPhysicalMethod(o.fullName)
1003
+ });
1004
+ x.participantIDs.push(o.userFbId);
1005
+ }
1006
+ }
1007
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
1008
+ }
1009
+ break;
1010
+ case "log:unsubscribe": {
1011
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
1012
+ x.participantIDs = x.participantIDs.filter(item => item != logMessageData.leftParticipantFbId);
1013
+ x.userInfo = x.userInfo.filter(item => item.id != logMessageData.leftParticipantFbId);
1014
+ if (x.adminIDs.some(i => i.id == logMessageData.leftParticipantFbId)) {
1015
+ x.adminIDs = x.adminIDs.filter(item => item.id != logMessageData.leftParticipantFbId);
1016
+ }
1017
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
1018
+ }
1019
+ break;
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ return {
1025
+ type: "event",
1026
+ threadID: formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),
1027
+ logMessageType: logMessageType,
1028
+ logMessageData: logMessageData,
1029
+ logMessageBody: m.messageMetadata.adminText,
1030
+ author: m.messageMetadata.actorFbId,
1031
+ participantIDs: m.participants || []
1032
+ };
1033
+ }
1034
+
1035
+ /**
1036
+ * @param {{ st: any; from: { toString: () => any; }; to: any; thread_fbid: any; hasOwnProperty: (arg0: string) => any; from_mobile: any; realtime_viewer_fbid: any; }} event
1037
+ */
1038
+
1039
+ function formatTyp(event) {
1040
+ return {
1041
+ isTyping: !!event.st,
1042
+ from: event.from.toString(),
1043
+ threadID: formatID((event.to || event.thread_fbid || event.from).toString()),
1044
+ // When receiving typ indication from mobile, `from_mobile` isn't set.
1045
+ // If it is, we just use that value.
1046
+ fromMobile: event.hasOwnProperty("from_mobile") ? event.from_mobile : true,
1047
+ userID: (event.realtime_viewer_fbid || event.from).toString(),
1048
+ type: "typ"
1049
+ };
1050
+ }
1051
+
1052
+ /**
1053
+ * @param {{ threadKey: { otherUserFbId: any; threadFbId: any; }; actorFbId: any; actionTimestampMs: any; }} delta
1054
+ */
1055
+
1056
+ function formatDeltaReadReceipt(delta) {
1057
+ // otherUserFbId seems to be used as both the readerID and the threadID in a 1-1 chat.
1058
+ // In a group chat actorFbId is used for the reader and threadFbId for the thread.
1059
+ return {
1060
+ reader: (delta.threadKey.otherUserFbId || delta.actorFbId).toString(),
1061
+ time: delta.actionTimestampMs,
1062
+ threadID: formatID((delta.threadKey.otherUserFbId || delta.threadKey.threadFbId).toString()),
1063
+ type: "read_receipt"
1064
+ };
1065
+ }
1066
+
1067
+ /**
1068
+ * @param {{ reader: { toString: () => any; }; time: any; thread_fbid: any; }} event
1069
+ */
1070
+
1071
+ function formatReadReceipt(event) {
1072
+ return {
1073
+ reader: event.reader.toString(),
1074
+ time: event.time,
1075
+ threadID: formatID((event.thread_fbid || event.reader).toString()),
1076
+ type: "read_receipt"
1077
+ };
1078
+ }
1079
+
1080
+ /**
1081
+ * @param {{ chat_ids: any[]; thread_fbids: any[]; timestamp: any; }} event
1082
+ */
1083
+
1084
+ function formatRead(event) {
1085
+ return {
1086
+ threadID: formatID(((event.chat_ids && event.chat_ids[0]) || (event.thread_fbids && event.thread_fbids[0])).toString()),
1087
+ time: event.timestamp,
1088
+ type: "read"
1089
+ };
1090
+ }
1091
+
1092
+ /**
1093
+ * @param {string} str
1094
+ * @param {string | any[]} startToken
1095
+ * @param {string} endToken
1096
+ */
1097
+
1098
+ function getFrom(str, startToken, endToken) {
1099
+ var start = str.indexOf(startToken) + startToken.length;
1100
+ if (start < startToken.length) return "";
1101
+
1102
+ var lastHalf = str.substring(start);
1103
+ var end = lastHalf.indexOf(endToken);
1104
+ if (end === -1) throw Error("Could not find endTime `" + endToken + "` in the given string.");
1105
+ return lastHalf.substring(0, end);
1106
+ }
1107
+
1108
+ /**
1109
+ * @param {string} html
1110
+ */
1111
+
1112
+ function makeParsable(html) {
1113
+ let withoutForLoop = html.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/
1114
+ , "");
1115
+
1116
+ // (What the fuck FB, why windows style newlines?)
1117
+ // So sometimes FB will send us base multiple objects in the same response.
1118
+ // They're all valid JSON, one after the other, at the top level. We detect
1119
+ // that and make it parse-able by JSON.parse.
1120
+ // Ben - July 15th 2017
1121
+ //
1122
+ // It turns out that Facebook may insert random number of spaces before
1123
+ // next object begins (issue #616)
1124
+ // rav_kr - 2018-03-19
1125
+ let maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
1126
+ if (maybeMultipleObjects.length === 1) return maybeMultipleObjects;
1127
+
1128
+ return "[" + maybeMultipleObjects.join("},{") + "]";
1129
+ }
1130
+
1131
+ /**
1132
+ * @param {any} form
1133
+ */
1134
+
1135
+ function arrToForm(form) {
1136
+ return arrayToObject(form,
1137
+ function(/** @type {{ name: any; }} */v) {
1138
+ return v.name;
1139
+ },
1140
+ function(/** @type {{ val: any; }} */v) {
1141
+ return v.val;
1142
+ }
1143
+ );
1144
+ }
1145
+
1146
+ /**
1147
+ * @param {any[]} arr
1148
+ * @param {{ (v: any): any; (arg0: any): string | number; }} getKey
1149
+ * @param {{ (v: any): any; (arg0: any): any; }} getValue
1150
+ */
1151
+
1152
+ function arrayToObject(arr, getKey, getValue) {
1153
+ return arr.reduce(function(/** @type {{ [x: string]: any; }} */
1154
+ acc, /** @type {any} */val) {
1155
+ acc[getKey(val)] = getValue(val);
1156
+ return acc;
1157
+ }, {});
1158
+ }
1159
+
1160
+ function getSignatureID() {
1161
+ return Math.floor(Math.random() * 2147483648).toString(16);
1162
+ }
1163
+
1164
+ function generateTimestampRelative() {
1165
+ var d = new Date();
1166
+ return d.getHours() + ":" + padZeros(d.getMinutes());
1167
+ }
1168
+
1169
+ /**
1170
+ * @param {any} html
1171
+ * @param {any} userID
1172
+ * @param {{ fb_dtsg: any; ttstamp: any; globalOptions: any; }} ctx
1173
+ */
1174
+
1175
+ function makeDefaults(html, userID, ctx) {
1176
+ var reqCounter = 1;
1177
+ var fb_dtsg = getFrom(html, 'name="fb_dtsg" value="', '"');
1178
+
1179
+ // @Hack Ok we've done hacky things, this is definitely on top 5.
1180
+ // We totally assume the object is flat and try parsing until a }.
1181
+ // If it works though it's cool because we get a bunch of extra data things.
1182
+ //
1183
+ // Update: we don't need this. Leaving it in in case we ever do.
1184
+ // Ben - July 15th 2017
1185
+
1186
+ // var siteData = getFrom(html, "[\"SiteData\",[],", "},");
1187
+ // try {
1188
+ // siteData = JSON.parse(siteData + "}");
1189
+ // } catch(e) {
1190
+ // log.warn("makeDefaults", "Couldn't parse SiteData. Won't have access to some variables.");
1191
+ // siteData = {};
1192
+ // }
1193
+
1194
+ var ttstamp = "2";
1195
+ for (var i = 0; i < fb_dtsg.length; i++) ttstamp += fb_dtsg.charCodeAt(i);
1196
+ var revision = getFrom(html, 'revision":', ",");
1197
+
1198
+ /**
1199
+ * @param {{ [x: string]: any; hasOwnProperty: (arg0: string) => any; }} obj
1200
+ */
1201
+
1202
+ function mergeWithDefaults(obj) {
1203
+ // @TODO This is missing a key called __dyn.
1204
+ // After some investigation it seems like __dyn is some sort of set that FB
1205
+ // calls BitMap. It seems like certain responses have a "define" key in the
1206
+ // res.jsmods arrays. I think the code iterates over those and calls `set`
1207
+ // on the bitmap for each of those keys. Then it calls
1208
+ // bitmap.toCompressedString() which returns what __dyn is.
1209
+ //
1210
+ // So far the API has been working without this.
1211
+ //
1212
+ // Ben - July 15th 2017
1213
+ var newObj = {
1214
+ __user: userID,
1215
+ __req: (reqCounter++).toString(36),
1216
+ __rev: revision,
1217
+ __a: 1,
1218
+ // __af: siteData.features,
1219
+ fb_dtsg: ctx.fb_dtsg ? ctx.fb_dtsg : fb_dtsg,
1220
+ jazoest: ctx.ttstamp ? ctx.ttstamp : ttstamp
1221
+ // __spin_r: siteData.__spin_r,
1222
+ // __spin_b: siteData.__spin_b,
1223
+ // __spin_t: siteData.__spin_t,
1224
+ };
1225
+
1226
+ // @TODO this is probably not needed.
1227
+ // Ben - July 15th 2017
1228
+ // if (siteData.be_key) {
1229
+ // newObj[siteData.be_key] = siteData.be_mode;
1230
+ // }
1231
+ // if (siteData.pkg_cohort_key) {
1232
+ // newObj[siteData.pkg_cohort_key] = siteData.pkg_cohort;
1233
+ // }
1234
+
1235
+ if (!obj) return newObj;
1236
+ for (var prop in obj)
1237
+ if (obj.hasOwnProperty(prop))
1238
+ if (!newObj[prop]) newObj[prop] = obj[prop];
1239
+ return newObj;
1240
+ }
1241
+
1242
+ /**
1243
+ * @param {any} url
1244
+ * @param {any} jar
1245
+ * @param {any} form
1246
+ * @param {any} ctxx
1247
+ */
1248
+
1249
+ function postWithDefaults(url, jar, form, ctxx) {
1250
+ return post(url, jar, mergeWithDefaults(form), ctx.globalOptions, ctxx || ctx);
1251
+ }
1252
+
1253
+ /**
1254
+ * @param {any} url
1255
+ * @param {any} jar
1256
+ * @param {any} qs
1257
+ * @param {any} ctxx
1258
+ */
1259
+
1260
+ function getWithDefaults(url, jar, qs, ctxx) {
1261
+ return get(url, jar, mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
1262
+ }
1263
+
1264
+ /**
1265
+ * @param {any} url
1266
+ * @param {any} jar
1267
+ * @param {any} form
1268
+ * @param {any} qs
1269
+ * @param {any} ctxx
1270
+ */
1271
+
1272
+ function postFormDataWithDefault(url, jar, form, qs, ctxx) {
1273
+ return postFormData(url, jar, mergeWithDefaults(form), mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
1274
+ }
1275
+
1276
+ return {
1277
+ get: getWithDefaults,
1278
+ post: postWithDefaults,
1279
+ postFormData: postFormDataWithDefault
1280
+ };
1281
+ }
1282
+
1283
+ /**
1284
+ * @param {{ jar: { setCookie: (arg0: string, arg1: string) => void; }; fb_dtsg: string; ttstamp: string; }} ctx
1285
+ * @param {{ postFormData: (arg0: string, arg1: any, arg2: any, arg3: {}) => any; post: (arg0: string, arg1: any, arg2: any) => any; get: (arg0: any, arg1: any) => Promise<any>; }} defaultFuncs
1286
+ * @param {string | number} [retryCount]
1287
+ */
1288
+
1289
+ function parseAndCheckLogin(ctx, defaultFuncs, retryCount) {
1290
+ if (retryCount == undefined) retryCount = 0;
1291
+ return function(/** @type {{ body: string; statusCode: string | number; request: { uri: { protocol: string; hostname: string; pathname: string; }; headers: { [x: string]: string; }; formData: any; method: string; }; }} */data) {
1292
+ return bluebird.try(function() {
1293
+ log.verbose("parseAndCheckLogin", data.body);
1294
+ if (data.statusCode >= 500 && data.statusCode < 600) {
1295
+ if (retryCount >= 5) {
1296
+ throw {
1297
+ error: "Request retry failed. Check the `res` and `statusCode` property on this error.",
1298
+ statusCode: data.statusCode,
1299
+ res: data.body
1300
+ };
1301
+ }
1302
+ retryCount++;
1303
+ var retryTime = Math.floor(Math.random() * 5000);
1304
+ log.warn("parseAndCheckLogin", "Got status code " + data.statusCode + " - " + retryCount + ". attempt to retry in " + retryTime + " milliseconds...");
1305
+ var url = data.request.uri.protocol + "//" + data.request.uri.hostname + data.request.uri.pathname;
1306
+ if (data.request.headers["Content-Type"].split(";")[0] === "multipart/form-data") {
1307
+ return bluebird.delay(retryTime).then(() => defaultFuncs.postFormData(url, ctx.jar, data.request.formData, {}))
1308
+ .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
1309
+ } else {
1310
+ return bluebird.delay(retryTime).then(() => defaultFuncs.post(url, ctx.jar, data.request.formData))
1311
+ .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
1312
+ }
1313
+ }
1314
+ if (data.statusCode !== 200) throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
1315
+
1316
+ var res = null;
1317
+ try {
1318
+ res = JSON.parse(makeParsable(data.body));
1319
+ } catch (e) {
1320
+ throw {
1321
+ error: "JSON.parse error. Check the `detail` property on this error.",
1322
+ detail: e,
1323
+ res: data.body
1324
+ };
1325
+ }
1326
+
1327
+ // In some cases the response contains only a redirect URL which should be followed
1328
+ if (res.redirect && data.request.method === "GET") return defaultFuncs.get(res.redirect, ctx.jar).then(parseAndCheckLogin(ctx, defaultFuncs));
1329
+
1330
+ // TODO: handle multiple cookies?
1331
+ if (res.jsmods && res.jsmods.require && Array.isArray(res.jsmods.require[0]) && res.jsmods.require[0][0] === "Cookie") {
1332
+ res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
1333
+ var cookie = formatCookie(res.jsmods.require[0][3], "facebook");
1334
+ var cookie2 = formatCookie(res.jsmods.require[0][3], "messenger");
1335
+ ctx.jar.setCookie(cookie, "https://www.facebook.com");
1336
+ ctx.jar.setCookie(cookie2, "https://www.messenger.com");
1337
+ }
1338
+
1339
+ // On every request we check if we got a DTSG and we mutate the context so that we use the latest
1340
+ // one for the next requests.
1341
+ if (res.jsmods && Array.isArray(res.jsmods.require)) {
1342
+ var arr = res.jsmods.require;
1343
+ for (var i in arr) {
1344
+ if (arr[i][0] === "DTSG" && arr[i][1] === "setToken") {
1345
+ ctx.fb_dtsg = arr[i][3][0];
1346
+
1347
+ // Update ttstamp since that depends on fb_dtsg
1348
+ ctx.ttstamp = "2";
1349
+ for (var j = 0; j < ctx.fb_dtsg.length; j++) ctx.ttstamp += ctx.fb_dtsg.charCodeAt(j);
1350
+ }
1351
+ }
1352
+ }
1353
+
1354
+ if (res.error === 1357001) {
1355
+ if (global.Fca.Require.FastConfig.AutoLogin) {
1356
+ return global.Fca.Require.logger.Warning(global.Fca.Require.Language.Index.AutoLogin, function() {
1357
+ return global.Fca.Action('AutoLogin');
1358
+ });
1359
+ }
1360
+ else if (!global.Fca.Require.FastConfig.AutoLogin) {
1361
+ return global.Fca.Require.logger.Error(global.Fca.Require.Language.Index.ErrAppState);
1362
+ }
1363
+ return;
1364
+ }
1365
+ else return res;
1366
+ });
1367
+ };
1368
+ }
1369
+
1370
+ /**
1371
+ * @param {{ setCookie: (arg0: any, arg1: string) => void; }} jar
1372
+ */
1373
+
1374
+ function saveCookies(jar) {
1375
+ return function(/** @type {{ headers: { [x: string]: any[]; }; }} */res) {
1376
+ var cookies = res.headers["set-cookie"] || [];
1377
+ cookies.forEach(function(/** @type {string} */c) {
1378
+ if (c.indexOf(".facebook.com") > -1) { // yo wtf is this?
1379
+ jar.setCookie(c, "https://www.facebook.com");
1380
+ jar.setCookie(c.replace(/domain=\.facebook\.com/, "domain=.messenger.com"), "https://www.messenger.com");
1381
+ }
1382
+ });
1383
+ return res;
1384
+ };
1385
+ }
1386
+
1387
+ var NUM_TO_MONTH = [
1388
+ "Jan",
1389
+ "Feb",
1390
+ "Mar",
1391
+ "Apr",
1392
+ "May",
1393
+ "Jun",
1394
+ "Jul",
1395
+ "Aug",
1396
+ "Sep",
1397
+ "Oct",
1398
+ "Nov",
1399
+ "Dec"
1400
+ ];
1401
+ var NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
1402
+
1403
+ /**
1404
+ * @param {{ getUTCDate: () => any; getUTCHours: () => any; getUTCMinutes: () => any; getUTCSeconds: () => any; getUTCDay: () => string | number; getUTCMonth: () => string | number; getUTCFullYear: () => string; }} date
1405
+ */
1406
+
1407
+ function formatDate(date) {
1408
+ var d = date.getUTCDate();
1409
+ d = d >= 10 ? d : "0" + d;
1410
+ var h = date.getUTCHours();
1411
+ h = h >= 10 ? h : "0" + h;
1412
+ var m = date.getUTCMinutes();
1413
+ m = m >= 10 ? m : "0" + m;
1414
+ var s = date.getUTCSeconds();
1415
+ s = s >= 10 ? s : "0" + s;
1416
+ return (NUM_TO_DAY[date.getUTCDay()] + ", " + d + " " + NUM_TO_MONTH[date.getUTCMonth()] + " " + date.getUTCFullYear() + " " + h + ":" + m + ":" + s + " GMT");
1417
+ }
1418
+
1419
+ /**
1420
+ * @param {string[]} arr
1421
+ * @param {string} url
1422
+ */
1423
+
1424
+ function formatCookie(arr, url) {
1425
+ return arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + url + ".com";
1426
+ }
1427
+
1428
+ /**
1429
+ * @param {{ thread_fbid: { toString: () => any; }; participants: any[]; name: any; custom_nickname: any; snippet: any; snippet_attachments: any; snippet_sender: any; unread_count: any; message_count: any; image_src: any; timestamp: any; mute_until: any; is_canonical_user: any; is_canonical: any; is_subscribed: any; folder: any; is_archived: any; recipients_loadable: any; has_email_participant: any; read_only: any; can_reply: any; cannot_reply_reason: any; last_message_timestamp: any; last_read_timestamp: any; last_message_type: any; custom_like_icon: any; custom_color: any; admin_ids: any; thread_type: any; }} data
1430
+ */
1431
+
1432
+ function formatThread(data) {
1433
+ return {
1434
+ threadID: formatID(data.thread_fbid.toString()),
1435
+ participants: data.participants.map(formatID),
1436
+ participantIDs: data.participants.map(formatID),
1437
+ name: data.name,
1438
+ nicknames: data.custom_nickname,
1439
+ snippet: data.snippet,
1440
+ snippetAttachments: data.snippet_attachments,
1441
+ snippetSender: formatID((data.snippet_sender || "").toString()),
1442
+ unreadCount: data.unread_count,
1443
+ messageCount: data.message_count,
1444
+ imageSrc: data.image_src,
1445
+ timestamp: data.timestamp,
1446
+ muteUntil: data.mute_until,
1447
+ isCanonicalUser: data.is_canonical_user,
1448
+ isCanonical: data.is_canonical,
1449
+ isSubscribed: data.is_subscribed,
1450
+ folder: data.folder,
1451
+ isArchived: data.is_archived,
1452
+ recipientsLoadable: data.recipients_loadable,
1453
+ hasEmailParticipant: data.has_email_participant,
1454
+ readOnly: data.read_only,
1455
+ canReply: data.can_reply,
1456
+ cannotReplyReason: data.cannot_reply_reason,
1457
+ lastMessageTimestamp: data.last_message_timestamp,
1458
+ lastReadTimestamp: data.last_read_timestamp,
1459
+ lastMessageType: data.last_message_type,
1460
+ emoji: data.custom_like_icon,
1461
+ color: data.custom_color,
1462
+ adminIDs: data.admin_ids,
1463
+ threadType: data.thread_type
1464
+ };
1465
+ }
1466
+
1467
+ /**
1468
+ * @param {any} obj
1469
+ */
1470
+
1471
+ function getType(obj) {
1472
+ return Object.prototype.toString.call(obj).slice(8, -1);
1473
+ }
1474
+
1475
+ /**
1476
+ * @param {{ lat: number; p: any; }} presence
1477
+ * @param {any} userID
1478
+ */
1479
+
1480
+ function formatProxyPresence(presence, userID) {
1481
+ if (presence.lat === undefined || presence.p === undefined) return null;
1482
+ return {
1483
+ type: "presence",
1484
+ timestamp: presence.lat * 1000,
1485
+ userID: userID || '',
1486
+ statuses: presence.p
1487
+ };
1488
+ }
1489
+
1490
+ /**
1491
+ * @param {{ la: number; a: any; }} presence
1492
+ * @param {any} userID
1493
+ */
1494
+
1495
+ function formatPresence(presence, userID) {
1496
+ return {
1497
+ type: "presence",
1498
+ timestamp: presence.la * 1000,
1499
+ userID: userID || '',
1500
+ statuses: presence.a
1501
+ };
1502
+ }
1503
+
1504
+ /**
1505
+ * @param {any} payload
1506
+ */
1507
+
1508
+ function decodeClientPayload(payload) {
1509
+ /*
1510
+ Special function which Client using to "encode" clients JSON payload
1511
+ */
1512
+
1513
+ /**
1514
+ * @param {string | any[]} array
1515
+ */
1516
+
1517
+ function Utf8ArrayToStr(array) {
1518
+ var out, i, len, c;
1519
+ var char2, char3;
1520
+ out = "";
1521
+ len = array.length;
1522
+ i = 0;
1523
+ while (i < len) {
1524
+ c = array[i++];
1525
+ switch (c >> 4) {
1526
+ case 0:
1527
+ case 1:
1528
+ case 2:
1529
+ case 3:
1530
+ case 4:
1531
+ case 5:
1532
+ case 6:
1533
+ case 7:
1534
+ out += String.fromCharCode(c);
1535
+ break;
1536
+ case 12:
1537
+ case 13:
1538
+ char2 = array[i++];
1539
+ out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
1540
+ break;
1541
+ case 14:
1542
+ char2 = array[i++];
1543
+ char3 = array[i++];
1544
+ out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
1545
+ break;
1546
+ }
1547
+ }
1548
+ return out;
1549
+ }
1550
+ return JSON.parse(Utf8ArrayToStr(payload));
1551
+ }
1552
+
1553
+ /**
1554
+ * @param {{ getCookies: (arg0: string) => string | any[]; }} jar
1555
+ */
1556
+
1557
+ function getAppState(jar, Encode) {
1558
+ var prettyMilliseconds = require('pretty-ms');
1559
+ var getText = globalThis.Fca.getText;
1560
+ var Security = require("./Extra/Security/Base");
1561
+ var appstate = jar.getCookies("https://www.facebook.com").concat(jar.getCookies("https://facebook.com")).concat(jar.getCookies("https://www.messenger.com"));
1562
+ var logger = require('./logger'),languageFile = require('./Language/index.json');
1563
+ var Language = languageFile.find(i => i.Language == globalThis.Fca.Require.FastConfig.Language).Folder.Index;
1564
+ var data;
1565
+ switch (require(process.cwd() + "/FastConfigFca.json").EncryptFeature) {
1566
+ case true: {
1567
+ if (Encode == undefined) Encode = true;
1568
+ if (process.env['FBKEY'] != undefined && Encode) {
1569
+ logger.Normal(Language.EncryptSuccess);
1570
+ data = Security(JSON.stringify(appstate),process.env['FBKEY'],"Encrypt");
1571
+ }
1572
+ else return appstate;
1573
+ }
1574
+ break;
1575
+ case false: {
1576
+ data = appstate;
1577
+ }
1578
+ break;
1579
+ default: {
1580
+ logger.Normal(getText(Language.IsNotABoolean,require(process.cwd() + "/FastConfigFca.json").EncryptFeature));
1581
+ data = appstate;
1582
+ }
1583
+ }
1584
+ if(!globalThis.Fca.Setting.get('getAppState')) {
1585
+ logger.Normal(getText(Language.ProcessDone,`${prettyMilliseconds(Date.now() - globalThis.Fca.startTime)}`),function() { globalThis.Fca.Setting.set('getAppState',true); });
1586
+ }
1587
+ return data;
1588
+ }
1589
+
1590
+ function getData_Path(Obj , Arr, Stt) {
1591
+ //default stt = 0
1592
+ if (Arr.length === 0 && Obj != undefined) {
1593
+ return Obj; //object
1594
+ }
1595
+ else if (Obj == undefined) {
1596
+ return Stt;
1597
+ }
1598
+ const head = Arr[0];
1599
+ if (head == undefined) {
1600
+ return Stt;
1601
+ }
1602
+ const tail = Arr.slice(1);
1603
+ return getData_Path(Obj[head], tail, Stt++);
1604
+ }
1605
+
1606
+
1607
+ function setData_Path(obj, path, value) {
1608
+ if (!path.length) {
1609
+ return obj;
1610
+ }
1611
+ const currentKey = path[0];
1612
+ let currentObj = obj[currentKey];
1613
+
1614
+ if (!currentObj) {
1615
+ obj[currentKey] = value;
1616
+ currentObj = obj[currentKey];
1617
+ }
1618
+ path.shift();
1619
+ if (!path.length) {
1620
+ currentObj = value;
1621
+ } else {
1622
+ currentObj = setData_Path(currentObj, path, value);
1623
+ }
1624
+
1625
+ return obj;
1626
+ }
1627
+
1628
+ function getPaths(obj, parentPath = []) {
1629
+ let paths = [];
1630
+ for (let prop in obj) {
1631
+ if (typeof obj[prop] === "object") {
1632
+ paths = paths.concat(getPaths(obj[prop], [...parentPath, prop]));
1633
+ } else {
1634
+ paths.push([...parentPath, prop]);
1635
+ }
1636
+ }
1637
+ return paths;
1638
+ }
1639
+
1640
+ module.exports = {
1641
+ isReadableStream:isReadableStream,
1642
+ get:get,
1643
+ post:post,
1644
+ postFormData:postFormData,
1645
+ generateThreadingID:generateThreadingID,
1646
+ generateOfflineThreadingID:generateOfflineThreadingID,
1647
+ getGUID:getGUID,
1648
+ getFrom:getFrom,
1649
+ makeParsable:makeParsable,
1650
+ arrToForm:arrToForm,
1651
+ getSignatureID:getSignatureID,
1652
+ getJar: request.jar,
1653
+ generateTimestampRelative:generateTimestampRelative,
1654
+ makeDefaults:makeDefaults,
1655
+ parseAndCheckLogin:parseAndCheckLogin,
1656
+ getGender: getGenderByPhysicalMethod,
1657
+ getData_Path,
1658
+ setData_Path,
1659
+ getPaths,
1660
+ saveCookies,
1661
+ getType,
1662
+ _formatAttachment,
1663
+ formatHistoryMessage,
1664
+ formatID,
1665
+ formatMessage,
1666
+ formatDeltaEvent,
1667
+ formatDeltaMessage,
1668
+ formatProxyPresence,
1669
+ formatPresence,
1670
+ formatTyp,
1671
+ formatDeltaReadReceipt,
1672
+ formatCookie,
1673
+ formatThread,
1674
+ formatReadReceipt,
1675
+ formatRead,
1676
+ generatePresence,
1677
+ generateAccessiblityCookie,
1678
+ formatDate,
1679
+ decodeClientPayload,
1680
+ getAppState,
1681
+ getAdminTextMessageType,
1682
+ setProxy
1683
+ };