fca-nayan-r 1.4.8

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

Potentially problematic release.


This version of fca-nayan-r might be problematic. Click here for more details.

Files changed (120) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -0
  2. package/.cache/replit/nix/env.json +1 -0
  3. package/.config/configstore/update-notifier-npm.json +4 -0
  4. package/.config/configstore/update-notifier-npm.json.1735545094 +4 -0
  5. package/.gitattributes +2 -0
  6. package/.replit +80 -0
  7. package/.upm/store.json +1 -0
  8. package/Extra/Database/index.js +469 -0
  9. package/Extra/ExtraAddons.js +82 -0
  10. package/Extra/ExtraFindUID.js +62 -0
  11. package/Extra/ExtraGetThread.js +340 -0
  12. package/Extra/ExtraScreenShot.js +430 -0
  13. package/Extra/ExtraUptimeRobot.js +38 -0
  14. package/Extra/Html/Classic/script.js +119 -0
  15. package/Extra/Html/Classic/style.css +8 -0
  16. package/Extra/Security/Index.js +146 -0
  17. package/Extra/Security/Step_1.js +6 -0
  18. package/Extra/Security/Step_2.js +22 -0
  19. package/Extra/Security/Step_3.js +22 -0
  20. package/Extra/Src/Change_Environment.js +24 -0
  21. package/Extra/Src/Check_Update.js +67 -0
  22. package/Extra/Src/History.js +115 -0
  23. package/Extra/Src/Instant_Update.js +65 -0
  24. package/Extra/Src/Last-Run.js +65 -0
  25. package/Extra/Src/Premium.js +81 -0
  26. package/Extra/Src/Release_Memory.js +41 -0
  27. package/Extra/Src/uuid.js +137 -0
  28. package/Func/AcceptAgreement.js +32 -0
  29. package/Func/ClearCache.js +64 -0
  30. package/Func/ReportV1.js +54 -0
  31. package/LICENSE +21 -0
  32. package/Language/index.json +207 -0
  33. package/Main.js +1095 -0
  34. package/README.md +140 -0
  35. package/SECURITY.md +17 -0
  36. package/broadcast.js +40 -0
  37. package/index.js +351 -0
  38. package/logger.js +66 -0
  39. package/package.json +94 -0
  40. package/replit.nix +8 -0
  41. package/src/Dev_Horizon_Data.js +125 -0
  42. package/src/Premium.js +30 -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 +440 -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 +790 -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 +334 -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/Nayan_Database/A_README.md +1 -0
  106. package/test/Nayan_Database/Database.db +0 -0
  107. package/test/Nayan_Database/N +1 -0
  108. package/test/data/shareAttach.js +146 -0
  109. package/test/data/something.mov +0 -0
  110. package/test/data/test.png +0 -0
  111. package/test/data/test.txt +7 -0
  112. package/test/env/.env +0 -0
  113. package/test/env.env +0 -0
  114. package/test/example-config.json +18 -0
  115. package/test/example-db.db +0 -0
  116. package/test/memoryleak.js +18 -0
  117. package/test/test-page.js +140 -0
  118. package/test/test.js +385 -0
  119. package/test/testv2.js +18 -0
  120. package/utils.js +1639 -0
package/utils.js ADDED
@@ -0,0 +1,1639 @@
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
+
941
+ if (process.env.HalzionVersion == 1973) {
942
+ switch (hasData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()))) {
943
+ case true: {
944
+ switch (logMessageType) {
945
+ case "log:thread-color": {
946
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
947
+ x.emoji = (logMessageData.theme_emoji || x.emoji);
948
+ x.color = (logMessageData['theme_color'] || x.color);
949
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
950
+ }
951
+ break;
952
+ case "log:thread-icon": {
953
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
954
+ x.emoji = (logMessageData['thread_icon'] || x.emoji);
955
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
956
+ }
957
+ break;
958
+ case "log:user-nickname": {
959
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
960
+ x.nicknames[logMessageData.participant_id] = (logMessageData.nickname.length == 0 ? x.userInfo.find(i => i.id == String(logMessageData.participant_id)).name : logMessageData.nickname);
961
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
962
+ }
963
+ break;
964
+ case "log:thread-admins": {
965
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
966
+ switch (logMessageData.ADMIN_EVENT) {
967
+ case "add_admin": {
968
+ x.adminIDs.push({ id: logMessageData.TARGET_ID });
969
+ }
970
+ break;
971
+ case "remove_admin": {
972
+ x.adminIDs = x.adminIDs.filter(item => item.id != logMessageData.TARGET_ID);
973
+ }
974
+ break;
975
+ }
976
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
977
+ }
978
+ break;
979
+ case "log:thread-approval-mode": {
980
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
981
+ if (x.approvalMode == true) {
982
+ x.approvalMode = false;
983
+ }
984
+ else {
985
+ x.approvalMode = true;
986
+ }
987
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
988
+ }
989
+ break;
990
+ case "log:thread-name": {
991
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
992
+ x.threadName = (logMessageData.name || formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
993
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
994
+ }
995
+ break;
996
+ case "log:subscribe": {
997
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
998
+ for (let o of logMessageData.addedParticipants) {
999
+ if (x.userInfo.some(i => i.id == o.userFbId)) continue;
1000
+ else {
1001
+ x.userInfo.push({
1002
+ id: o.userFbId,
1003
+ name: o.fullName,
1004
+ gender: getGenderByPhysicalMethod(o.fullName)
1005
+ });
1006
+ x.participantIDs.push(o.userFbId);
1007
+ }
1008
+ }
1009
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
1010
+ }
1011
+ break;
1012
+ case "log:unsubscribe": {
1013
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
1014
+ x.participantIDs = x.participantIDs.filter(item => item != logMessageData.leftParticipantFbId);
1015
+ x.userInfo = x.userInfo.filter(item => item.id != logMessageData.leftParticipantFbId);
1016
+ if (x.adminIDs.some(i => i.id == logMessageData.leftParticipantFbId)) {
1017
+ x.adminIDs = x.adminIDs.filter(item => item.id != logMessageData.leftParticipantFbId);
1018
+ }
1019
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
1020
+ }
1021
+ break;
1022
+ }
1023
+ }
1024
+ }
1025
+ }
1026
+
1027
+ return {
1028
+ type: "event",
1029
+ threadID: formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),
1030
+ logMessageType: logMessageType,
1031
+ logMessageData: logMessageData,
1032
+ logMessageBody: m.messageMetadata.adminText,
1033
+ author: m.messageMetadata.actorFbId,
1034
+ participantIDs: m.participants || []
1035
+ };
1036
+ }
1037
+
1038
+ /**
1039
+ * @param {{ st: any; from: { toString: () => any; }; to: any; thread_fbid: any; hasOwnProperty: (arg0: string) => any; from_mobile: any; realtime_viewer_fbid: any; }} event
1040
+ */
1041
+
1042
+ function formatTyp(event) {
1043
+ return {
1044
+ isTyping: !!event.st,
1045
+ from: event.from.toString(),
1046
+ threadID: formatID((event.to || event.thread_fbid || event.from).toString()),
1047
+ // When receiving typ indication from mobile, `from_mobile` isn't set.
1048
+ // If it is, we just use that value.
1049
+ fromMobile: event.hasOwnProperty("from_mobile") ? event.from_mobile : true,
1050
+ userID: (event.realtime_viewer_fbid || event.from).toString(),
1051
+ type: "typ"
1052
+ };
1053
+ }
1054
+
1055
+ /**
1056
+ * @param {{ threadKey: { otherUserFbId: any; threadFbId: any; }; actorFbId: any; actionTimestampMs: any; }} delta
1057
+ */
1058
+
1059
+ function formatDeltaReadReceipt(delta) {
1060
+ // otherUserFbId seems to be used as both the readerID and the threadID in a 1-1 chat.
1061
+ // In a group chat actorFbId is used for the reader and threadFbId for the thread.
1062
+ return {
1063
+ reader: (delta.threadKey.otherUserFbId || delta.actorFbId).toString(),
1064
+ time: delta.actionTimestampMs,
1065
+ threadID: formatID((delta.threadKey.otherUserFbId || delta.threadKey.threadFbId).toString()),
1066
+ type: "read_receipt"
1067
+ };
1068
+ }
1069
+
1070
+ /**
1071
+ * @param {{ reader: { toString: () => any; }; time: any; thread_fbid: any; }} event
1072
+ */
1073
+
1074
+ function formatReadReceipt(event) {
1075
+ return {
1076
+ reader: event.reader.toString(),
1077
+ time: event.time,
1078
+ threadID: formatID((event.thread_fbid || event.reader).toString()),
1079
+ type: "read_receipt"
1080
+ };
1081
+ }
1082
+
1083
+ /**
1084
+ * @param {{ chat_ids: any[]; thread_fbids: any[]; timestamp: any; }} event
1085
+ */
1086
+
1087
+ function formatRead(event) {
1088
+ return {
1089
+ threadID: formatID(((event.chat_ids && event.chat_ids[0]) || (event.thread_fbids && event.thread_fbids[0])).toString()),
1090
+ time: event.timestamp,
1091
+ type: "read"
1092
+ };
1093
+ }
1094
+
1095
+ /**
1096
+ * @param {string} str
1097
+ * @param {string | any[]} startToken
1098
+ * @param {string} endToken
1099
+ */
1100
+
1101
+ function getFrom(str, startToken, endToken) {
1102
+ var start = str.indexOf(startToken) + startToken.length;
1103
+ if (start < startToken.length) return "";
1104
+
1105
+ var lastHalf = str.substring(start);
1106
+ var end = lastHalf.indexOf(endToken);
1107
+ if (end === -1) throw Error("Could not find endTime `" + endToken + "` in the given string.");
1108
+ return lastHalf.substring(0, end);
1109
+ }
1110
+
1111
+ /**
1112
+ * @param {string} html
1113
+ */
1114
+
1115
+ function makeParsable(html) {
1116
+ let withoutForLoop = html.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/
1117
+ , "");
1118
+
1119
+ // (What the fuck FB, why windows style newlines?)
1120
+ // So sometimes FB will send us base multiple objects in the same response.
1121
+ // They're all valid JSON, one after the other, at the top level. We detect
1122
+ // that and make it parse-able by JSON.parse.
1123
+ // Ben - July 15th 2017
1124
+ //
1125
+ // It turns out that Facebook may insert random number of spaces before
1126
+ // next object begins (issue #616)
1127
+ // rav_kr - 2018-03-19
1128
+ let maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
1129
+ if (maybeMultipleObjects.length === 1) return maybeMultipleObjects;
1130
+
1131
+ return "[" + maybeMultipleObjects.join("},{") + "]";
1132
+ }
1133
+
1134
+ /**
1135
+ * @param {any} form
1136
+ */
1137
+
1138
+ function arrToForm(form) {
1139
+ return arrayToObject(form,
1140
+ function(/** @type {{ name: any; }} */v) {
1141
+ return v.name;
1142
+ },
1143
+ function(/** @type {{ val: any; }} */v) {
1144
+ return v.val;
1145
+ }
1146
+ );
1147
+ }
1148
+
1149
+ /**
1150
+ * @param {any[]} arr
1151
+ * @param {{ (v: any): any; (arg0: any): string | number; }} getKey
1152
+ * @param {{ (v: any): any; (arg0: any): any; }} getValue
1153
+ */
1154
+
1155
+ function arrayToObject(arr, getKey, getValue) {
1156
+ return arr.reduce(function(/** @type {{ [x: string]: any; }} */
1157
+ acc, /** @type {any} */val) {
1158
+ acc[getKey(val)] = getValue(val);
1159
+ return acc;
1160
+ }, {});
1161
+ }
1162
+
1163
+ function getSignatureID() {
1164
+ return Math.floor(Math.random() * 2147483648).toString(16);
1165
+ }
1166
+
1167
+ function generateTimestampRelative() {
1168
+ var d = new Date();
1169
+ return d.getHours() + ":" + padZeros(d.getMinutes());
1170
+ }
1171
+
1172
+ /**
1173
+ * @param {any} html
1174
+ * @param {any} userID
1175
+ * @param {{ fb_dtsg: any; ttstamp: any; globalOptions: any; }} ctx
1176
+ */
1177
+
1178
+ function makeDefaults(html, userID, ctx) {
1179
+ var reqCounter = 1;
1180
+ var fb_dtsg = getFrom(html, 'name="fb_dtsg" value="', '"');
1181
+
1182
+ // @Hack Ok we've done hacky things, this is definitely on top 5.
1183
+ // We totally assume the object is flat and try parsing until a }.
1184
+ // If it works though it's cool because we get a bunch of extra data things.
1185
+ //
1186
+ // Update: we don't need this. Leaving it in in case we ever do.
1187
+ // Ben - July 15th 2017
1188
+
1189
+ // var siteData = getFrom(html, "[\"SiteData\",[],", "},");
1190
+ // try {
1191
+ // siteData = JSON.parse(siteData + "}");
1192
+ // } catch(e) {
1193
+ // log.warn("makeDefaults", "Couldn't parse SiteData. Won't have access to some variables.");
1194
+ // siteData = {};
1195
+ // }
1196
+
1197
+ var ttstamp = "2";
1198
+ for (var i = 0; i < fb_dtsg.length; i++) ttstamp += fb_dtsg.charCodeAt(i);
1199
+ var revision = getFrom(html, 'revision":', ",");
1200
+
1201
+ /**
1202
+ * @param {{ [x: string]: any; hasOwnProperty: (arg0: string) => any; }} obj
1203
+ */
1204
+
1205
+ function mergeWithDefaults(obj) {
1206
+ // @TODO This is missing a key called __dyn.
1207
+ // After some investigation it seems like __dyn is some sort of set that FB
1208
+ // calls BitMap. It seems like certain responses have a "define" key in the
1209
+ // res.jsmods arrays. I think the code iterates over those and calls `set`
1210
+ // on the bitmap for each of those keys. Then it calls
1211
+ // bitmap.toCompressedString() which returns what __dyn is.
1212
+ //
1213
+ // So far the API has been working without this.
1214
+ //
1215
+ // Ben - July 15th 2017
1216
+ var newObj = {
1217
+ __user: userID,
1218
+ __req: (reqCounter++).toString(36),
1219
+ __rev: revision,
1220
+ __a: 1,
1221
+ // __af: siteData.features,
1222
+ fb_dtsg: ctx.fb_dtsg ? ctx.fb_dtsg : fb_dtsg,
1223
+ jazoest: ctx.ttstamp ? ctx.ttstamp : ttstamp
1224
+ // __spin_r: siteData.__spin_r,
1225
+ // __spin_b: siteData.__spin_b,
1226
+ // __spin_t: siteData.__spin_t,
1227
+ };
1228
+
1229
+ // @TODO this is probably not needed.
1230
+ // Ben - July 15th 2017
1231
+ // if (siteData.be_key) {
1232
+ // newObj[siteData.be_key] = siteData.be_mode;
1233
+ // }
1234
+ // if (siteData.pkg_cohort_key) {
1235
+ // newObj[siteData.pkg_cohort_key] = siteData.pkg_cohort;
1236
+ // }
1237
+
1238
+ if (!obj) return newObj;
1239
+ for (var prop in obj)
1240
+ if (obj.hasOwnProperty(prop))
1241
+ if (!newObj[prop]) newObj[prop] = obj[prop];
1242
+ return newObj;
1243
+ }
1244
+
1245
+ /**
1246
+ * @param {any} url
1247
+ * @param {any} jar
1248
+ * @param {any} form
1249
+ * @param {any} ctxx
1250
+ */
1251
+
1252
+ function postWithDefaults(url, jar, form, ctxx) {
1253
+ return post(url, jar, mergeWithDefaults(form), ctx.globalOptions, ctxx || ctx);
1254
+ }
1255
+
1256
+ /**
1257
+ * @param {any} url
1258
+ * @param {any} jar
1259
+ * @param {any} qs
1260
+ * @param {any} ctxx
1261
+ */
1262
+
1263
+ function getWithDefaults(url, jar, qs, ctxx) {
1264
+ return get(url, jar, mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
1265
+ }
1266
+
1267
+ /**
1268
+ * @param {any} url
1269
+ * @param {any} jar
1270
+ * @param {any} form
1271
+ * @param {any} qs
1272
+ * @param {any} ctxx
1273
+ */
1274
+
1275
+ function postFormDataWithDefault(url, jar, form, qs, ctxx) {
1276
+ return postFormData(url, jar, mergeWithDefaults(form), mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
1277
+ }
1278
+
1279
+ return {
1280
+ get: getWithDefaults,
1281
+ post: postWithDefaults,
1282
+ postFormData: postFormDataWithDefault
1283
+ };
1284
+ }
1285
+
1286
+ /**
1287
+ * @param {{ jar: { setCookie: (arg0: string, arg1: string) => void; }; fb_dtsg: string; ttstamp: string; }} ctx
1288
+ * @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
1289
+ * @param {string | number} [retryCount]
1290
+ */
1291
+
1292
+ function parseAndCheckLogin(ctx, defaultFuncs, retryCount) {
1293
+ if (retryCount == undefined) retryCount = 0;
1294
+ 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) {
1295
+ return bluebird.try(function() {
1296
+ log.verbose("parseAndCheckLogin", data.body);
1297
+ if (data.statusCode >= 500 && data.statusCode < 600) {
1298
+ if (retryCount >= 5) {
1299
+ throw {
1300
+ error: "Request retry failed. Check the `res` and `statusCode` property on this error.",
1301
+ statusCode: data.statusCode,
1302
+ res: data.body
1303
+ };
1304
+ }
1305
+ retryCount++;
1306
+ var retryTime = Math.floor(Math.random() * 5000);
1307
+ log.warn("parseAndCheckLogin", "Got status code " + data.statusCode + " - " + retryCount + ". attempt to retry in " + retryTime + " milliseconds...");
1308
+ var url = data.request.uri.protocol + "//" + data.request.uri.hostname + data.request.uri.pathname;
1309
+ if (data.request.headers["Content-Type"].split(";")[0] === "multipart/form-data") {
1310
+ return bluebird.delay(retryTime).then(() => defaultFuncs.postFormData(url, ctx.jar, data.request.formData, {}))
1311
+ .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
1312
+ } else {
1313
+ return bluebird.delay(retryTime).then(() => defaultFuncs.post(url, ctx.jar, data.request.formData))
1314
+ .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
1315
+ }
1316
+ }
1317
+ if (data.statusCode !== 200) throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
1318
+
1319
+ var res = null;
1320
+ try {
1321
+ res = JSON.parse(makeParsable(data.body));
1322
+ } catch (e) {
1323
+ throw {
1324
+ error: "JSON.parse error. Check the `detail` property on this error.",
1325
+ detail: e,
1326
+ res: data.body
1327
+ };
1328
+ }
1329
+
1330
+ // In some cases the response contains only a redirect URL which should be followed
1331
+ if (res.redirect && data.request.method === "GET") return defaultFuncs.get(res.redirect, ctx.jar).then(parseAndCheckLogin(ctx, defaultFuncs));
1332
+
1333
+ // TODO: handle multiple cookies?
1334
+ if (res.jsmods && res.jsmods.require && Array.isArray(res.jsmods.require[0]) && res.jsmods.require[0][0] === "Cookie") {
1335
+ res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
1336
+ var cookie = formatCookie(res.jsmods.require[0][3], "facebook");
1337
+ var cookie2 = formatCookie(res.jsmods.require[0][3], "messenger");
1338
+ ctx.jar.setCookie(cookie, "https://www.facebook.com");
1339
+ ctx.jar.setCookie(cookie2, "https://www.messenger.com");
1340
+ }
1341
+
1342
+ // On every request we check if we got a DTSG and we mutate the context so that we use the latest
1343
+ // one for the next requests.
1344
+ if (res.jsmods && Array.isArray(res.jsmods.require)) {
1345
+ var arr = res.jsmods.require;
1346
+ for (var i in arr) {
1347
+ if (arr[i][0] === "DTSG" && arr[i][1] === "setToken") {
1348
+ ctx.fb_dtsg = arr[i][3][0];
1349
+
1350
+ // Update ttstamp since that depends on fb_dtsg
1351
+ ctx.ttstamp = "2";
1352
+ for (var j = 0; j < ctx.fb_dtsg.length; j++) ctx.ttstamp += ctx.fb_dtsg.charCodeAt(j);
1353
+ }
1354
+ }
1355
+ }
1356
+
1357
+ if (res.error === 1357001) {
1358
+ if (global.Fca.Require.FastConfig.AutoLogin) {
1359
+ return global.Fca.Require.logger.Warning(global.Fca.Require.Language.Index.AutoLogin, function() {
1360
+ return global.Fca.Action('AutoLogin');
1361
+ });
1362
+ }
1363
+ else if (!global.Fca.Require.FastConfig.AutoLogin) {
1364
+ return global.Fca.Require.logger.Error(global.Fca.Require.Language.Index.ErrAppState);
1365
+ }
1366
+ return;
1367
+ }
1368
+ else return res;
1369
+ });
1370
+ };
1371
+ }
1372
+
1373
+ /**
1374
+ * @param {{ setCookie: (arg0: any, arg1: string) => void; }} jar
1375
+ */
1376
+
1377
+ function saveCookies(jar) {
1378
+ return function(/** @type {{ headers: { [x: string]: any[]; }; }} */res) {
1379
+ var cookies = res.headers["set-cookie"] || [];
1380
+ cookies.forEach(function(/** @type {string} */c) {
1381
+ if (c.indexOf(".facebook.com") > -1) { // yo wtf is this?
1382
+ jar.setCookie(c, "https://www.facebook.com");
1383
+ jar.setCookie(c.replace(/domain=\.facebook\.com/, "domain=.messenger.com"), "https://www.messenger.com");
1384
+ }
1385
+ });
1386
+ return res;
1387
+ };
1388
+ }
1389
+
1390
+ var NUM_TO_MONTH = [
1391
+ "Jan",
1392
+ "Feb",
1393
+ "Mar",
1394
+ "Apr",
1395
+ "May",
1396
+ "Jun",
1397
+ "Jul",
1398
+ "Aug",
1399
+ "Sep",
1400
+ "Oct",
1401
+ "Nov",
1402
+ "Dec"
1403
+ ];
1404
+ var NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
1405
+
1406
+ /**
1407
+ * @param {{ getUTCDate: () => any; getUTCHours: () => any; getUTCMinutes: () => any; getUTCSeconds: () => any; getUTCDay: () => string | number; getUTCMonth: () => string | number; getUTCFullYear: () => string; }} date
1408
+ */
1409
+
1410
+ function formatDate(date) {
1411
+ var d = date.getUTCDate();
1412
+ d = d >= 10 ? d : "0" + d;
1413
+ var h = date.getUTCHours();
1414
+ h = h >= 10 ? h : "0" + h;
1415
+ var m = date.getUTCMinutes();
1416
+ m = m >= 10 ? m : "0" + m;
1417
+ var s = date.getUTCSeconds();
1418
+ s = s >= 10 ? s : "0" + s;
1419
+ return (NUM_TO_DAY[date.getUTCDay()] + ", " + d + " " + NUM_TO_MONTH[date.getUTCMonth()] + " " + date.getUTCFullYear() + " " + h + ":" + m + ":" + s + " GMT");
1420
+ }
1421
+
1422
+ /**
1423
+ * @param {string[]} arr
1424
+ * @param {string} url
1425
+ */
1426
+
1427
+ function formatCookie(arr, url) {
1428
+ return arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + url + ".com";
1429
+ }
1430
+
1431
+ /**
1432
+ * @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
1433
+ */
1434
+
1435
+ function formatThread(data) {
1436
+ return {
1437
+ threadID: formatID(data.thread_fbid.toString()),
1438
+ participants: data.participants.map(formatID),
1439
+ participantIDs: data.participants.map(formatID),
1440
+ name: data.name,
1441
+ nicknames: data.custom_nickname,
1442
+ snippet: data.snippet,
1443
+ snippetAttachments: data.snippet_attachments,
1444
+ snippetSender: formatID((data.snippet_sender || "").toString()),
1445
+ unreadCount: data.unread_count,
1446
+ messageCount: data.message_count,
1447
+ imageSrc: data.image_src,
1448
+ timestamp: data.timestamp,
1449
+ muteUntil: data.mute_until,
1450
+ isCanonicalUser: data.is_canonical_user,
1451
+ isCanonical: data.is_canonical,
1452
+ isSubscribed: data.is_subscribed,
1453
+ folder: data.folder,
1454
+ isArchived: data.is_archived,
1455
+ recipientsLoadable: data.recipients_loadable,
1456
+ hasEmailParticipant: data.has_email_participant,
1457
+ readOnly: data.read_only,
1458
+ canReply: data.can_reply,
1459
+ cannotReplyReason: data.cannot_reply_reason,
1460
+ lastMessageTimestamp: data.last_message_timestamp,
1461
+ lastReadTimestamp: data.last_read_timestamp,
1462
+ lastMessageType: data.last_message_type,
1463
+ emoji: data.custom_like_icon,
1464
+ color: data.custom_color,
1465
+ adminIDs: data.admin_ids,
1466
+ threadType: data.thread_type
1467
+ };
1468
+ }
1469
+
1470
+ /**
1471
+ * @param {any} obj
1472
+ */
1473
+
1474
+ function getType(obj) {
1475
+ return Object.prototype.toString.call(obj).slice(8, -1);
1476
+ }
1477
+
1478
+ /**
1479
+ * @param {{ lat: number; p: any; }} presence
1480
+ * @param {any} userID
1481
+ */
1482
+
1483
+ function formatProxyPresence(presence, userID) {
1484
+ if (presence.lat === undefined || presence.p === undefined) return null;
1485
+ return {
1486
+ type: "presence",
1487
+ timestamp: presence.lat * 1000,
1488
+ userID: userID || '',
1489
+ statuses: presence.p
1490
+ };
1491
+ }
1492
+
1493
+ /**
1494
+ * @param {{ la: number; a: any; }} presence
1495
+ * @param {any} userID
1496
+ */
1497
+
1498
+ function formatPresence(presence, userID) {
1499
+ return {
1500
+ type: "presence",
1501
+ timestamp: presence.la * 1000,
1502
+ userID: userID || '',
1503
+ statuses: presence.a
1504
+ };
1505
+ }
1506
+
1507
+ /**
1508
+ * @param {any} payload
1509
+ */
1510
+
1511
+ function decodeClientPayload(payload) {
1512
+ /*
1513
+ Special function which Client using to "encode" clients JSON payload
1514
+ */
1515
+
1516
+ /**
1517
+ * @param {string | any[]} array
1518
+ */
1519
+
1520
+ function Utf8ArrayToStr(array) {
1521
+ var out, i, len, c;
1522
+ var char2, char3;
1523
+ out = "";
1524
+ len = array.length;
1525
+ i = 0;
1526
+ while (i < len) {
1527
+ c = array[i++];
1528
+ switch (c >> 4) {
1529
+ case 0:
1530
+ case 1:
1531
+ case 2:
1532
+ case 3:
1533
+ case 4:
1534
+ case 5:
1535
+ case 6:
1536
+ case 7:
1537
+ out += String.fromCharCode(c);
1538
+ break;
1539
+ case 12:
1540
+ case 13:
1541
+ char2 = array[i++];
1542
+ out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
1543
+ break;
1544
+ case 14:
1545
+ char2 = array[i++];
1546
+ char3 = array[i++];
1547
+ out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
1548
+ break;
1549
+ }
1550
+ }
1551
+ return out;
1552
+ }
1553
+ return JSON.parse(Utf8ArrayToStr(payload));
1554
+ }
1555
+
1556
+ /**
1557
+ * @param {{ getCookies: (arg0: string) => string | any[]; }} jar
1558
+ */
1559
+
1560
+ function getAppState(jar, Encode) {
1561
+ var prettyMilliseconds = require('pretty-ms');
1562
+ var getText = globalThis.Fca.getText;
1563
+ var Security = require("./Extra/Security/Index");
1564
+ var appstate = jar.getCookies("https://www.facebook.com").concat(jar.getCookies("https://facebook.com")).concat(jar.getCookies("https://www.messenger.com"));
1565
+ var logger = require('./logger'),languageFile = require('./Language/index.json');
1566
+ var Language = languageFile.find(i => i.Language == globalThis.Fca.Require.FastConfig.Language).Folder.Index;
1567
+ var data;
1568
+ switch (require(process.cwd() + "/FastConfigFca.json").EncryptFeature) {
1569
+ case true: {
1570
+ if (Encode == undefined) Encode = true;
1571
+ if (process.env['FBKEY'] != undefined && Encode) {
1572
+ if(!globalThis.Fca.Setting.get('getAppState')) {
1573
+ logger.Normal(Language.EncryptSuccess);
1574
+ data = Security(JSON.stringify(appstate),process.env['FBKEY'],"Encrypt");
1575
+ globalThis.Fca.Setting.set('AppState', data);
1576
+ }
1577
+ else {
1578
+ data = globalThis.Fca.Setting.get('AppState');
1579
+ }
1580
+ }
1581
+ else return appstate;
1582
+ }
1583
+ break;
1584
+ case false: {
1585
+ data = appstate;
1586
+ }
1587
+ break;
1588
+ default: {
1589
+ logger.Normal(getText(Language.IsNotABoolean,require(process.cwd() + "/FastConfigFca.json").EncryptFeature));
1590
+ data = appstate;
1591
+ }
1592
+ }
1593
+ if(!globalThis.Fca.Setting.get('getAppState')) {
1594
+ logger.Normal(getText(Language.ProcessDone,`${prettyMilliseconds(Date.now() - globalThis.Fca.startTime)}`),function() { globalThis.Fca.Setting.set('getAppState',true); });
1595
+ }
1596
+ return data;
1597
+ }
1598
+
1599
+ module.exports = {
1600
+ isReadableStream:isReadableStream,
1601
+ get:get,
1602
+ post:post,
1603
+ postFormData:postFormData,
1604
+ generateThreadingID:generateThreadingID,
1605
+ generateOfflineThreadingID:generateOfflineThreadingID,
1606
+ getGUID:getGUID,
1607
+ getFrom:getFrom,
1608
+ makeParsable:makeParsable,
1609
+ arrToForm:arrToForm,
1610
+ getSignatureID:getSignatureID,
1611
+ getJar: request.jar,
1612
+ generateTimestampRelative:generateTimestampRelative,
1613
+ makeDefaults:makeDefaults,
1614
+ parseAndCheckLogin:parseAndCheckLogin,
1615
+ getGender: getGenderByPhysicalMethod,
1616
+ saveCookies,
1617
+ getType,
1618
+ _formatAttachment,
1619
+ formatHistoryMessage,
1620
+ formatID,
1621
+ formatMessage,
1622
+ formatDeltaEvent,
1623
+ formatDeltaMessage,
1624
+ formatProxyPresence,
1625
+ formatPresence,
1626
+ formatTyp,
1627
+ formatDeltaReadReceipt,
1628
+ formatCookie,
1629
+ formatThread,
1630
+ formatReadReceipt,
1631
+ formatRead,
1632
+ generatePresence,
1633
+ generateAccessiblityCookie,
1634
+ formatDate,
1635
+ decodeClientPayload,
1636
+ getAppState,
1637
+ getAdminTextMessageType,
1638
+ setProxy
1639
+ };