fca-dongdev-remake 0.0.1-security → 1.7.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-dongdev-remake might be problematic. Click here for more details.

Files changed (112) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -0
  2. package/.cache/replit/modules.stamp +1 -0
  3. package/.cache/replit/nix/env.json +1 -0
  4. package/.gitattributes +2 -0
  5. package/.upm/store.json +1 -0
  6. package/DOCS.md +1738 -0
  7. package/Extra/ExtraAddons.js +78 -0
  8. package/Extra/ExtraFindUID.js +60 -0
  9. package/Extra/ExtraGetThread.js +118 -0
  10. package/Extra/ExtraScreenShot.js +673 -0
  11. package/Extra/ExtraTranslate.js +62 -0
  12. package/Extra/ExtraUptimeRobot.js +59 -0
  13. package/Extra/Html/Classic/script.js +231 -0
  14. package/Extra/Html/Classic/style.css +8 -0
  15. package/Extra/PM2/ecosystem.config.js +23 -0
  16. package/Extra/Security/Index.js +146 -0
  17. package/Extra/Security/Step_1.js +11 -0
  18. package/Extra/Security/Step_2.js +20 -0
  19. package/Extra/Security/Step_3.js +20 -0
  20. package/Extra/Src/History.js +115 -0
  21. package/Extra/Src/Last-Run.js +65 -0
  22. package/Extra/Src/Premium.js +84 -0
  23. package/Extra/Src/SecurityCheck.js +2 -0
  24. package/Func/AcceptAgreement.js +32 -0
  25. package/Func/ClearCache.js +64 -0
  26. package/Func/ReportV1.js +54 -0
  27. package/Horizon_Package/Synthetic-Horizon-Database/index.js +358 -0
  28. package/Horizon_Package/Synthetic-Horizon-Database/package-lock.json +2945 -0
  29. package/Horizon_Package/Synthetic-Horizon-Database/package.json +27 -0
  30. package/Horizon_Package/Synthetic-Horizon-Database/readme.md +8 -0
  31. package/Horizon_Package/horizon-sp/README.md +11 -0
  32. package/Horizon_Package/horizon-sp/index.js +41 -0
  33. package/Horizon_Package/horizon-sp/logger.js +16 -0
  34. package/Horizon_Package/horizon-sp/package-lock.json +150 -0
  35. package/Horizon_Package/horizon-sp/package.json +20 -0
  36. package/LICENSE.md +23 -0
  37. package/Language/index.json +176 -0
  38. package/OldSecurity.js +100 -0
  39. package/README.md +125 -3
  40. package/SECURITY.md +21 -0
  41. package/Settngs/Database.js +21 -0
  42. package/Settngs/Location.js +59 -0
  43. package/Settngs/Location.json +24 -0
  44. package/Settngs/Settings.js +59 -0
  45. package/StateCrypt.js +98 -0
  46. package/broadcast.js +38 -0
  47. package/index.js +1333 -0
  48. package/logger.js +65 -0
  49. package/package.json +89 -3
  50. package/src/Horizon_Data.js +125 -0
  51. package/src/K2IMG.js +8 -0
  52. package/src/Premium.js +30 -0
  53. package/src/Screenshot.js +85 -0
  54. package/src/T2S.js +8 -0
  55. package/src/addExternalModule.js +16 -0
  56. package/src/addUserToGroup.js +79 -0
  57. package/src/changeAdminStatus.js +79 -0
  58. package/src/changeArchivedStatus.js +41 -0
  59. package/src/changeAvt.js +85 -0
  60. package/src/changeBio.js +65 -0
  61. package/src/changeBlockedStatus.js +36 -0
  62. package/src/changeGroupImage.js +106 -0
  63. package/src/changeNickname.js +45 -0
  64. package/src/changeThreadColor.js +62 -0
  65. package/src/changeThreadEmoji.js +42 -0
  66. package/src/createNewGroup.js +70 -0
  67. package/src/createPoll.js +60 -0
  68. package/src/deleteMessage.js +45 -0
  69. package/src/deleteThread.js +43 -0
  70. package/src/forwardAttachment.js +48 -0
  71. package/src/getAccessToken.js +32 -0
  72. package/src/getCurrentUserID.js +7 -0
  73. package/src/getEmojiUrl.js +27 -0
  74. package/src/getFriendsList.js +73 -0
  75. package/src/getMessage.js +80 -0
  76. package/src/getThreadHistory.js +537 -0
  77. package/src/getThreadInfo.js +348 -0
  78. package/src/getThreadList.js +213 -0
  79. package/src/getThreadMain.js +219 -0
  80. package/src/getThreadPictures.js +59 -0
  81. package/src/getUID.js +59 -0
  82. package/src/getUserID.js +62 -0
  83. package/src/getUserInfo.js +129 -0
  84. package/src/getUserInfoMain.js +65 -0
  85. package/src/getUserInfoV2.js +36 -0
  86. package/src/getUserInfoV3.js +63 -0
  87. package/src/getUserInfoV4.js +55 -0
  88. package/src/getUserInfoV5.js +61 -0
  89. package/src/handleFriendRequest.js +46 -0
  90. package/src/handleMessageRequest.js +49 -0
  91. package/src/httpGet.js +49 -0
  92. package/src/httpPost.js +48 -0
  93. package/src/httpPostFormData.js +41 -0
  94. package/src/listenMqtt.js +702 -0
  95. package/src/logout.js +68 -0
  96. package/src/markAsDelivered.js +48 -0
  97. package/src/markAsRead.js +70 -0
  98. package/src/markAsReadAll.js +43 -0
  99. package/src/markAsSeen.js +51 -0
  100. package/src/muteThread.js +47 -0
  101. package/src/removeUserFromGroup.js +49 -0
  102. package/src/resolvePhotoUrl.js +37 -0
  103. package/src/searchForThread.js +43 -0
  104. package/src/sendMessage.js +334 -0
  105. package/src/sendTypingIndicator.js +80 -0
  106. package/src/setMessageReaction.js +109 -0
  107. package/src/setPostReaction.js +102 -0
  108. package/src/setTitle.js +74 -0
  109. package/src/threadColors.js +39 -0
  110. package/src/unfriend.js +43 -0
  111. package/src/unsendMessage.js +40 -0
  112. 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
+ };