fca-kizzdev 0.0.1-security → 8.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

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