fca-hnn 0.0.1-security → 91.4.0

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

Potentially problematic release.


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

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