fca-horidai-remastered 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. package/.gitattributes +2 -0
  2. package/Extra/Bypass/956/index.js +234 -0
  3. package/Extra/Bypass/test/aaaa.json +170 -0
  4. package/Extra/Bypass/test/index.js +188 -0
  5. package/Extra/Database/index.js +469 -0
  6. package/Extra/ExtraAddons.js +82 -0
  7. package/Extra/ExtraFindUID.js +62 -0
  8. package/Extra/ExtraGetThread.js +365 -0
  9. package/Extra/ExtraScreenShot.js +430 -0
  10. package/Extra/ExtraUptimeRobot.js +38 -0
  11. package/Extra/Html/Classic/script.js +119 -0
  12. package/Extra/Html/Classic/style.css +8 -0
  13. package/Extra/Security/AES_256_GCM/index.js +0 -0
  14. package/Extra/Security/Base/Step_1.js +6 -0
  15. package/Extra/Security/Base/Step_2.js +22 -0
  16. package/Extra/Security/Base/Step_3.js +22 -0
  17. package/Extra/Security/Base/index.js +191 -0
  18. package/Extra/Security/Index.js +5 -0
  19. package/Extra/Security/Step_1.js +6 -0
  20. package/Extra/Security/Step_2.js +22 -0
  21. package/Extra/Security/Step_3.js +22 -0
  22. package/Extra/Src/Change_Environment.js +24 -0
  23. package/Extra/Src/Check_Update.js +67 -0
  24. package/Extra/Src/History.js +115 -0
  25. package/Extra/Src/Instant_Update.js +65 -0
  26. package/Extra/Src/Last-Run.js +65 -0
  27. package/Extra/Src/Premium.js +81 -0
  28. package/Extra/Src/Release_Memory.js +160 -0
  29. package/Extra/Src/Websocket.js +213 -0
  30. package/Extra/Src/image/checkmate.jpg +0 -0
  31. package/Extra/Src/test.js +28 -0
  32. package/Extra/Src/uuid.js +137 -0
  33. package/Func/AcceptAgreement.js +31 -0
  34. package/Func/ClearCache.js +64 -0
  35. package/Func/ReportV1.js +54 -0
  36. package/LICENSE +21 -0
  37. package/Language/index.json +222 -0
  38. package/Main.js +1266 -0
  39. package/README.md +152 -0
  40. package/SECURITY.md +18 -0
  41. package/broadcast.js +44 -0
  42. package/index.js +448 -0
  43. package/logger.js +66 -0
  44. package/package.json +94 -0
  45. package/src/Dev_Horizon_Data.js +125 -0
  46. package/src/Dev_getThreadInfoOLD.js +422 -0
  47. package/src/Dev_shareTest2.js +68 -0
  48. package/src/Dev_shareTest3.js +71 -0
  49. package/src/Premium.js +25 -0
  50. package/src/Screenshot.js +83 -0
  51. package/src/addExternalModule.js +16 -0
  52. package/src/addUserToGroup.js +79 -0
  53. package/src/changeAdminStatus.js +79 -0
  54. package/src/changeArchivedStatus.js +41 -0
  55. package/src/changeAvt.js +85 -0
  56. package/src/changeBio.js +65 -0
  57. package/src/changeBlockedStatus.js +36 -0
  58. package/src/changeGroupImage.js +106 -0
  59. package/src/changeNickname.js +45 -0
  60. package/src/changeThreadColor.js +62 -0
  61. package/src/changeThreadEmoji.js +42 -0
  62. package/src/createNewGroup.js +70 -0
  63. package/src/createPoll.js +60 -0
  64. package/src/deleteMessage.js +45 -0
  65. package/src/deleteThread.js +43 -0
  66. package/src/editMessage.js +53 -0
  67. package/src/forwardAttachment.js +48 -0
  68. package/src/getAccessToken.js +28 -0
  69. package/src/getCurrentUserID.js +7 -0
  70. package/src/getEmojiUrl.js +27 -0
  71. package/src/getFriendsList.js +73 -0
  72. package/src/getMessage.js +103 -0
  73. package/src/getThreadHistory.js +537 -0
  74. package/src/getThreadInfo.js +424 -0
  75. package/src/getThreadInfoOLD.js +422 -0
  76. package/src/getThreadList.js +213 -0
  77. package/src/getThreadMain.js +220 -0
  78. package/src/getThreadPictures.js +59 -0
  79. package/src/getUID.js +59 -0
  80. package/src/getUserID.js +62 -0
  81. package/src/getUserInfo.js +112 -0
  82. package/src/getUserInfoMain.js +65 -0
  83. package/src/getUserInfoV2.js +32 -0
  84. package/src/getUserInfoV3.js +63 -0
  85. package/src/getUserInfoV4.js +55 -0
  86. package/src/getUserInfoV5.js +61 -0
  87. package/src/handleFriendRequest.js +46 -0
  88. package/src/handleMessageRequest.js +49 -0
  89. package/src/httpGet.js +49 -0
  90. package/src/httpPost.js +48 -0
  91. package/src/httpPostFormData.js +41 -0
  92. package/src/listenMqtt.js +936 -0
  93. package/src/listenMqttV1.js +846 -0
  94. package/src/logout.js +68 -0
  95. package/src/markAsDelivered.js +48 -0
  96. package/src/markAsRead.js +70 -0
  97. package/src/markAsReadAll.js +43 -0
  98. package/src/markAsSeen.js +51 -0
  99. package/src/muteThread.js +47 -0
  100. package/src/removeUserFromGroup.js +49 -0
  101. package/src/resolvePhotoUrl.js +37 -0
  102. package/src/searchForThread.js +43 -0
  103. package/src/sendMessage.js +386 -0
  104. package/src/sendMqttMessage.js +71 -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/shareContact.js +55 -0
  110. package/src/shareLink.js +58 -0
  111. package/src/threadColors.js +39 -0
  112. package/src/unfriend.js +43 -0
  113. package/src/unsendMessage.js +40 -0
  114. package/test/Database_Test.js +4 -0
  115. package/test/Db2.js +530 -0
  116. package/test/Horizon_Database/A_README.md +1 -0
  117. package/test/Horizon_Database/Database.db +0 -0
  118. package/test/data/shareAttach.js +146 -0
  119. package/test/data/something.mov +0 -0
  120. package/test/data/test.png +0 -0
  121. package/test/data/test.txt +7 -0
  122. package/test/env/.env +0 -0
  123. package/test/example-config.json +18 -0
  124. package/test/example-db.db +0 -0
  125. package/test/memoryleak.js +18 -0
  126. package/test/test-page.js +140 -0
  127. package/test/test.js +385 -0
  128. package/test/testname.js +1342 -0
  129. package/test/testv2.js +3 -0
  130. package/utils.js +3038 -0
package/utils.js ADDED
@@ -0,0 +1,3038 @@
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.messageMetadata;
727
+ var mdata =
728
+ m.data === undefined ? [] :
729
+ m.data.prng === undefined ? [] :
730
+ JSON.parse(m.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.body || "";
736
+ var args = body == "" ? [] : body.trim().split(/\s+/);
737
+ for (var i = 0; i < m_id.length; i++) mentions[m_id[i]] = m.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.attachments || []).map((/** @type {any} */v) => _formatAttachment(v)),
747
+ mentions: mentions,
748
+ timestamp: md.timestamp,
749
+ isGroup: !!md.threadKey.threadFbId,
750
+ participantIDs: m.participants || []
751
+ };
752
+ }
753
+
754
+ /**
755
+ * @param {string} id
756
+ */
757
+
758
+ function formatID(id) {
759
+ if (id != undefined && id != null) return id.replace(/(fb)?id[:.]/, "");
760
+ else return id;
761
+ }
762
+
763
+ /**
764
+ * @param {{ message: any; type: string; realtime_viewer_fbid: { toString: () => any; }; }} m
765
+ */
766
+
767
+ function formatMessage(m) {
768
+ var originalMessage = m.message ? m.message : m;
769
+ var obj = {
770
+ type: "message",
771
+ senderName: originalMessage.sender_name,
772
+ senderID: formatID(originalMessage.sender_fbid.toString()),
773
+ participantNames: originalMessage.group_thread_info ? originalMessage.group_thread_info.participant_names : [originalMessage.sender_name.split(" ")[0]],
774
+ participantIDs: originalMessage.group_thread_info ?
775
+ originalMessage.group_thread_info.participant_ids.map(function(/** @type {{ toString: () => any; }} */v) {
776
+ return formatID(v.toString());
777
+ }) : [formatID(originalMessage.sender_fbid)],
778
+ body: originalMessage.body || "",
779
+ threadID: formatID((originalMessage.thread_fbid || originalMessage.other_user_fbid).toString()),
780
+ threadName: originalMessage.group_thread_info ? originalMessage.group_thread_info.name : originalMessage.sender_name,
781
+ location: originalMessage.coordinates ? originalMessage.coordinates : null,
782
+ messageID: originalMessage.mid ? originalMessage.mid.toString() : originalMessage.message_id,
783
+ attachments: formatAttachment(
784
+ originalMessage.attachments,
785
+ originalMessage.attachmentIds,
786
+ originalMessage.attachment_map,
787
+ originalMessage.share_map
788
+ ),
789
+ timestamp: originalMessage.timestamp,
790
+ timestampAbsolute: originalMessage.timestamp_absolute,
791
+ timestampRelative: originalMessage.timestamp_relative,
792
+ timestampDatetime: originalMessage.timestamp_datetime,
793
+ tags: originalMessage.tags,
794
+ reactions: originalMessage.reactions ? originalMessage.reactions : [],
795
+ isUnread: originalMessage.is_unread
796
+ };
797
+
798
+ if (m.type === "pages_messaging") obj.pageID = m.realtime_viewer_fbid.toString();
799
+ obj.isGroup = obj.participantIDs.length > 2;
800
+
801
+ return obj;
802
+ }
803
+
804
+ /**
805
+ * @param {{ message: any; }} m
806
+ */
807
+
808
+ function formatEvent(m) {
809
+ var originalMessage = m.message ? m.message : m;
810
+ var logMessageType = originalMessage.log_message_type;
811
+ var logMessageData;
812
+ if (logMessageType === "log:generic-admin-text") {
813
+ logMessageData = originalMessage.log_message_data.untypedData;
814
+ logMessageType = getAdminTextMessageType(originalMessage.log_message_data.message_type);
815
+ } else logMessageData = originalMessage.log_message_data;
816
+
817
+ return Object.assign(formatMessage(originalMessage), {
818
+ type: "event",
819
+ logMessageType: logMessageType,
820
+ logMessageData: logMessageData,
821
+ logMessageBody: originalMessage.log_message_body
822
+ });
823
+ }
824
+
825
+ /**
826
+ * @param {{ action_type: any; }} m
827
+ */
828
+
829
+ function formatHistoryMessage(m) {
830
+ switch (m.action_type) {
831
+ case "ma-type:log-message":
832
+ return formatEvent(m);
833
+ default:
834
+ return formatMessage(m);
835
+ }
836
+ }
837
+
838
+ // Get a more readable message type for AdminTextMessages
839
+ /**
840
+ * @param {{ type: any; }} m
841
+ */
842
+
843
+ function getAdminTextMessageType(m) {
844
+ switch (m.type) {
845
+ case "joinable_group_link_mode_change":
846
+ return "log:link-status";
847
+ case "magic_words":
848
+ return "log:magic-words";
849
+ case "change_thread_theme":
850
+ return "log:thread-color";
851
+ case "change_thread_icon":
852
+ return "log:thread-icon";
853
+ case "change_thread_nickname":
854
+ return "log:user-nickname";
855
+ case "change_thread_admins":
856
+ return "log:thread-admins";
857
+ case "group_poll":
858
+ return "log:thread-poll";
859
+ case "change_thread_approval_mode":
860
+ return "log:thread-approval-mode";
861
+ case "messenger_call_log":
862
+ case "participant_joined_group_call":
863
+ return "log:thread-call";
864
+ case "pin_messages_v2":
865
+ return "log:thread-pinned";
866
+ }
867
+ }
868
+
869
+ /**
870
+ * @param {string} name
871
+ */
872
+
873
+ function getGenderByPhysicalMethod(name) {
874
+ const female_name = [
875
+ "Phương Chi",
876
+ "An Bình",
877
+ "An Di",
878
+ "An Hạ",
879
+ "An Hằng",
880
+ "An Khê",
881
+ "An Nhiên",
882
+ "An Nhàn",
883
+ "Anh Chi",
884
+ "Anh Hương",
885
+ "Anh Mai",
886
+ "Anh Phương",
887
+ "Anh Thi",
888
+ "Anh Thy",
889
+ "Anh Thơ",
890
+ "Anh Thư",
891
+ "Anh Thảo",
892
+ "Anh Vũ",
893
+ "Anh Ðào",
894
+ "Ban Mai",
895
+ "Bình Minh",
896
+ "Bình Yên",
897
+ "Bích Chiêu",
898
+ "Bích Châu",
899
+ "Bích Duyên",
900
+ "Bích Hiền",
901
+ "Bích Huệ",
902
+ "Bích Hà",
903
+ "Bích Hạnh",
904
+ "Bích Hải",
905
+ "Bích Hảo",
906
+ "Bích Hậu",
907
+ "Bích Hằng",
908
+ "Bích Hồng",
909
+ "Bích Hợp",
910
+ "Bích Lam",
911
+ "Bích Liên",
912
+ "Bích Loan",
913
+ "Bích Nga",
914
+ "Bích Ngà",
915
+ "Bích Ngân",
916
+ "Bích Ngọc",
917
+ "Bích Như",
918
+ "Bích Phượng",
919
+ "Bích Quyên",
920
+ "Bích Quân",
921
+ "Bích San",
922
+ "Bích Thoa",
923
+ "Bích Thu",
924
+ "Bích Thảo",
925
+ "Bích Thủy",
926
+ "Bích Trang",
927
+ "Bích Trâm",
928
+ "Bích Ty",
929
+ "Bích Vân",
930
+ "Bích Ðiệp",
931
+ "Bích Ðào",
932
+ "Băng Băng",
933
+ "Băng Tâm",
934
+ "Bạch Cúc",
935
+ "Bạch Hoa",
936
+ "Bạch Kim",
937
+ "Bạch Liên",
938
+ "Bạch Loan",
939
+ "Bạch Mai",
940
+ "Bạch Quỳnh",
941
+ "Bạch Trà",
942
+ "Bạch Tuyết",
943
+ "Bạch Vân",
944
+ "Bạch Yến",
945
+ "Bảo Anh",
946
+ "Bảo Bình",
947
+ "Bảo Châu",
948
+ "Bảo Huệ",
949
+ "Bảo Hà",
950
+ "Bảo Hân",
951
+ "Bảo Lan",
952
+ "Bảo Lễ",
953
+ "Bảo Ngọc",
954
+ "Bảo Phương",
955
+ "Bảo Quyên",
956
+ "Bảo Quỳnh",
957
+ "Bảo Thoa",
958
+ "Bảo Thúy",
959
+ "Bảo Tiên",
960
+ "Bảo Trâm",
961
+ "Bảo Trân",
962
+ "Bảo Trúc",
963
+ "Bảo Uyên",
964
+ "Bảo Vy",
965
+ "Bảo Vân",
966
+ "Bội Linh",
967
+ "Cam Thảo",
968
+ "Chi Lan",
969
+ "Chi Mai",
970
+ "Chiêu Dương",
971
+ "Cát Cát",
972
+ "Cát Linh",
973
+ "Cát Ly",
974
+ "Cát Tiên",
975
+ "Cát Tường",
976
+ "Cẩm Hiền",
977
+ "Cẩm Hường",
978
+ "Cẩm Hạnh",
979
+ "Cẩm Linh",
980
+ "Cẩm Liên",
981
+ "Cẩm Ly",
982
+ "Cẩm Nhi",
983
+ "Cẩm Nhung",
984
+ "Cẩm Thúy",
985
+ "Cẩm Tú",
986
+ "Cẩm Vân",
987
+ "Cẩm Yến",
988
+ "Di Nhiên",
989
+ "Diên Vỹ",
990
+ "Diễm Chi",
991
+ "Diễm Châu",
992
+ "Diễm Hương",
993
+ "Diễm Hạnh",
994
+ "Diễm Hằng",
995
+ "Diễm Khuê",
996
+ "Diễm Kiều",
997
+ "Diễm Liên",
998
+ "Diễm Lộc",
999
+ "Diễm My",
1000
+ "Diễm Phúc",
1001
+ "Diễm Phương",
1002
+ "Diễm Phước",
1003
+ "Diễm Phượng",
1004
+ "Diễm Quyên",
1005
+ "Diễm Quỳnh",
1006
+ "Diễm Thúy",
1007
+ "Diễm Thư",
1008
+ "Diễm Thảo",
1009
+ "Diễm Trang",
1010
+ "Diễm Trinh",
1011
+ "Diễm Uyên",
1012
+ "Diệp Anh",
1013
+ "Diệp Vy",
1014
+ "Diệu Anh",
1015
+ "Diệu Hiền",
1016
+ "Diệu Hoa",
1017
+ "Diệu Huyền",
1018
+ "Diệu Hương",
1019
+ "Diệu Hạnh",
1020
+ "Diệu Hằng",
1021
+ "Diệu Hồng",
1022
+ "Diệu Lan",
1023
+ "Diệu Linh",
1024
+ "Diệu Loan",
1025
+ "Diệu Nga",
1026
+ "Diệu Ngà",
1027
+ "Diệu Ngọc",
1028
+ "Diệu Nương",
1029
+ "Diệu Thiện",
1030
+ "Diệu Thúy",
1031
+ "Diệu Vân",
1032
+ "Diệu Ái",
1033
+ "Duy Hạnh",
1034
+ "Duy Mỹ",
1035
+ "Duy Uyên",
1036
+ "Duyên Hồng",
1037
+ "Duyên My",
1038
+ "Duyên Mỹ",
1039
+ "Duyên Nương",
1040
+ "Dã Lan",
1041
+ "Dã Lâm",
1042
+ "Dã Thảo",
1043
+ "Dạ Hương",
1044
+ "Dạ Lan",
1045
+ "Dạ Nguyệt",
1046
+ "Dạ Thi",
1047
+ "Dạ Thảo",
1048
+ "Dạ Yến",
1049
+ "Gia Hân",
1050
+ "Gia Khanh",
1051
+ "Gia Linh",
1052
+ "Gia Nhi",
1053
+ "Gia Quỳnh",
1054
+ "Giang Thanh",
1055
+ "Giang Thiên",
1056
+ "Giao Hưởng",
1057
+ "Giao Kiều",
1058
+ "Giao Linh",
1059
+ "Giáng Ngọc",
1060
+ "Giáng Tiên",
1061
+ "Giáng Uyên",
1062
+ "Hiếu Giang",
1063
+ "Hiếu Hạnh",
1064
+ "Hiếu Khanh",
1065
+ "Hiếu Minh",
1066
+ "Hiền Chung",
1067
+ "Hiền Hòa",
1068
+ "Hiền Mai",
1069
+ "Hiền Nhi",
1070
+ "Hiền Nương",
1071
+ "Hiền Thục",
1072
+ "Hiểu Lam",
1073
+ "Hiểu Vân",
1074
+ "Hoa Liên",
1075
+ "Hoa Lý",
1076
+ "Hoa Thiên",
1077
+ "Hoa Tiên",
1078
+ "Hoa Tranh",
1079
+ "Hoài An",
1080
+ "Hoài Giang",
1081
+ "Hoài Hương",
1082
+ "Hoài Phương",
1083
+ "Hoài Thương",
1084
+ "Hoài Trang",
1085
+ "Hoài Vỹ",
1086
+ "Hoàn Châu",
1087
+ "Hoàn Vi",
1088
+ "Hoàng Cúc",
1089
+ "Hoàng Hà",
1090
+ "Hoàng Kim",
1091
+ "Hoàng Lan",
1092
+ "Hoàng Mai",
1093
+ "Hoàng Miên",
1094
+ "Hoàng Nguyên",
1095
+ "Hoàng Oanh",
1096
+ "Hoàng Sa",
1097
+ "Hoàng Thư",
1098
+ "Hoàng Xuân",
1099
+ "Hoàng Yến",
1100
+ "Hoạ Mi",
1101
+ "Huyền Anh",
1102
+ "Huyền Diệu",
1103
+ "Huyền Linh",
1104
+ "Huyền Ngọc",
1105
+ "Huyền Nhi",
1106
+ "Huyền Thoại",
1107
+ "Huyền Thư",
1108
+ "Huyền Trang",
1109
+ "Huyền Trâm",
1110
+ "Huyền Trân",
1111
+ "Huệ An",
1112
+ "Huệ Hương",
1113
+ "Huệ Hồng",
1114
+ "Huệ Lan",
1115
+ "Huệ Linh",
1116
+ "Huệ Lâm",
1117
+ "Huệ My",
1118
+ "Huệ Phương",
1119
+ "Huệ Thương",
1120
+ "Huệ Ân",
1121
+ "Huỳnh Anh",
1122
+ "Hà Giang",
1123
+ "Hà Liên",
1124
+ "Hà Mi",
1125
+ "Hà My",
1126
+ "Hà Nhi",
1127
+ "Hà Phương",
1128
+ "Hà Thanh",
1129
+ "Hà Tiên",
1130
+ "Hàm Duyên",
1131
+ "Hàm Nghi",
1132
+ "Hàm Thơ",
1133
+ "Hàm Ý",
1134
+ "Hương Chi",
1135
+ "Hương Giang",
1136
+ "Hương Lan",
1137
+ "Hương Liên",
1138
+ "Hương Ly",
1139
+ "Hương Lâm",
1140
+ "Hương Mai",
1141
+ "Hương Nhi",
1142
+ "Hương Thu",
1143
+ "Hương Thảo",
1144
+ "Hương Thủy",
1145
+ "Hương Tiên",
1146
+ "Hương Trang",
1147
+ "Hương Trà",
1148
+ "Hương Xuân",
1149
+ "Hướng Dương",
1150
+ "Hạ Băng",
1151
+ "Hạ Giang",
1152
+ "Hạ Phương",
1153
+ "Hạ Tiên",
1154
+ "Hạ Uyên",
1155
+ "Hạ Vy",
1156
+ "Hạc Cúc",
1157
+ "Hạnh Chi",
1158
+ "Hạnh Dung",
1159
+ "Hạnh Linh",
1160
+ "Hạnh My",
1161
+ "Hạnh Nga",
1162
+ "Hạnh Nhơn",
1163
+ "Hạnh Phương",
1164
+ "Hạnh San",
1165
+ "Hạnh Thảo",
1166
+ "Hạnh Trang",
1167
+ "Hạnh Vi",
1168
+ "Hải Anh",
1169
+ "Hải Châu",
1170
+ "Hải Duyên",
1171
+ "Hải Dương",
1172
+ "Hải Miên",
1173
+ "Hải My",
1174
+ "Hải Mỹ",
1175
+ "Hải Ngân",
1176
+ "Hải Nhi",
1177
+ "Hải Phương",
1178
+ "Hải Phượng",
1179
+ "Hải San",
1180
+ "Hải Sinh",
1181
+ "Hải Thanh",
1182
+ "Hải Thảo",
1183
+ "Hải Thụy",
1184
+ "Hải Uyên",
1185
+ "Hải Vy",
1186
+ "Hải Vân",
1187
+ "Hải Yến",
1188
+ "Hải Ân",
1189
+ "Hải Ðường",
1190
+ "Hảo Nhi",
1191
+ "Hằng Anh",
1192
+ "Hằng Nga",
1193
+ "Họa Mi",
1194
+ "Hồ Diệp",
1195
+ "Hồng Anh",
1196
+ "Hồng Bạch Thảo",
1197
+ "Hồng Châu",
1198
+ "Hồng Diễm",
1199
+ "Hồng Giang",
1200
+ "Hồng Hoa",
1201
+ "Hồng Hà",
1202
+ "Hồng Hạnh",
1203
+ "Hồng Khanh",
1204
+ "Hồng Khuê",
1205
+ "Hồng Khôi",
1206
+ "Hồng Linh",
1207
+ "Hồng Liên",
1208
+ "Hồng Lâm",
1209
+ "Hồng Mai",
1210
+ "Hồng Nga",
1211
+ "Hồng Ngân",
1212
+ "Hồng Ngọc",
1213
+ "Hồng Nhung",
1214
+ "Hồng Như",
1215
+ "Hồng Nhạn",
1216
+ "Hồng Oanh",
1217
+ "Hồng Phúc",
1218
+ "Hồng Phương",
1219
+ "Hồng Quế",
1220
+ "Hồng Thu",
1221
+ "Hồng Thúy",
1222
+ "Hồng Thư",
1223
+ "Hồng Thảo",
1224
+ "Hồng Thắm",
1225
+ "Hồng Thủy",
1226
+ "Hồng Trúc",
1227
+ "Hồng Tâm",
1228
+ "Hồng Vân",
1229
+ "Hồng Xuân",
1230
+ "Hồng Ðiệp",
1231
+ "Hồng Ðào",
1232
+ "Hồng Đăng",
1233
+ "Khiết Linh",
1234
+ "Khiết Tâm",
1235
+ "Khuê Trung",
1236
+ "Khánh Chi",
1237
+ "Khánh Giang",
1238
+ "Khánh Giao",
1239
+ "Khánh Huyền",
1240
+ "Khánh Hà",
1241
+ "Khánh Hằng",
1242
+ "Khánh Linh",
1243
+ "Khánh Ly",
1244
+ "Khánh Mai",
1245
+ "Khánh My",
1246
+ "Khánh Ngân",
1247
+ "Khánh Ngọc",
1248
+ "Khánh Quyên",
1249
+ "Khánh Quỳnh",
1250
+ "Khánh Thủy",
1251
+ "Khánh Trang",
1252
+ "Khánh Vi",
1253
+ "Khánh Vy",
1254
+ "Khánh Vân",
1255
+ "Khúc Lan",
1256
+ "Khả Khanh",
1257
+ "Khả Tú",
1258
+ "Khả Ái",
1259
+ "Khải Ca",
1260
+ "Khải Hà",
1261
+ "Khải Tâm",
1262
+ "Kim Anh",
1263
+ "Kim Chi",
1264
+ "Kim Cương",
1265
+ "Kim Dung",
1266
+ "Kim Duyên",
1267
+ "Kim Hoa",
1268
+ "Kim Hương",
1269
+ "Kim Khanh",
1270
+ "Kim Khuyên",
1271
+ "Kim Khánh",
1272
+ "Kim Lan",
1273
+ "Kim Liên",
1274
+ "Kim Loan",
1275
+ "Kim Ly",
1276
+ "Kim Mai",
1277
+ "Kim Ngân",
1278
+ "Kim Ngọc",
1279
+ "Kim Oanh",
1280
+ "Kim Phượng",
1281
+ "Kim Quyên",
1282
+ "Kim Sa",
1283
+ "Kim Thanh",
1284
+ "Kim Thoa",
1285
+ "Kim Thu",
1286
+ "Kim Thy",
1287
+ "Kim Thông",
1288
+ "Kim Thư",
1289
+ "Kim Thảo",
1290
+ "Kim Thủy",
1291
+ "Kim Trang",
1292
+ "Kim Tuyến",
1293
+ "Kim Tuyết",
1294
+ "Kim Tuyền",
1295
+ "Kim Xuyến",
1296
+ "Kim Xuân",
1297
+ "Kim Yến",
1298
+ "Kim Ánh",
1299
+ "Kim Đan",
1300
+ "Kiết Hồng",
1301
+ "Kiết Trinh",
1302
+ "Kiều Anh",
1303
+ "Kiều Diễm",
1304
+ "Kiều Dung",
1305
+ "Kiều Giang",
1306
+ "Kiều Hoa",
1307
+ "Kiều Hạnh",
1308
+ "Kiều Khanh",
1309
+ "Kiều Loan",
1310
+ "Kiều Mai",
1311
+ "Kiều Minh",
1312
+ "Kiều Mỹ",
1313
+ "Kiều Nga",
1314
+ "Kiều Nguyệt",
1315
+ "Kiều Nương",
1316
+ "Kiều Thu",
1317
+ "Kiều Trang",
1318
+ "Kiều Trinh",
1319
+ "Kỳ Anh",
1320
+ "Kỳ Diệu",
1321
+ "Kỳ Duyên",
1322
+ "Lam Giang",
1323
+ "Lam Hà",
1324
+ "Lam Khê",
1325
+ "Lam Ngọc",
1326
+ "Lam Tuyền",
1327
+ "Lan Anh",
1328
+ "Lan Chi",
1329
+ "Lan Hương",
1330
+ "Lan Khuê",
1331
+ "Lan Ngọc",
1332
+ "Lan Nhi",
1333
+ "Lan Phương",
1334
+ "Lan Thương",
1335
+ "Lan Trúc",
1336
+ "Lan Vy",
1337
+ "Linh Chi",
1338
+ "Linh Châu",
1339
+ "Linh Duyên",
1340
+ "Linh Giang",
1341
+ "Linh Hà",
1342
+ "Linh Lan",
1343
+ "Linh Nhi",
1344
+ "Linh Phương",
1345
+ "Linh Phượng",
1346
+ "Linh San",
1347
+ "Linh Trang",
1348
+ "Linh Ðan",
1349
+ "Liên Chi",
1350
+ "Liên Hoa",
1351
+ "Liên Hương",
1352
+ "Liên Như",
1353
+ "Liên Phương",
1354
+ "Liên Trân",
1355
+ "Liễu Oanh",
1356
+ "Loan Châu",
1357
+ "Ly Châu",
1358
+ "Lâm Nhi",
1359
+ "Lâm Oanh",
1360
+ "Lâm Tuyền",
1361
+ "Lâm Uyên",
1362
+ "Lê Quỳnh",
1363
+ "Lưu Ly",
1364
+ "Lệ Băng",
1365
+ "Lệ Chi",
1366
+ "Lệ Giang",
1367
+ "Lệ Hoa",
1368
+ "Lệ Huyền",
1369
+ "Lệ Khanh",
1370
+ "Lệ Nga",
1371
+ "Lệ Nhi",
1372
+ "Lệ Quyên",
1373
+ "Lệ Quân",
1374
+ "Lệ Thanh",
1375
+ "Lệ Thu",
1376
+ "Lệ Thủy",
1377
+ "Lộc Uyên",
1378
+ "Lộc Uyển",
1379
+ "Lục Bình",
1380
+ "Mai Anh",
1381
+ "Mai Chi",
1382
+ "Mai Châu",
1383
+ "Mai Hiền",
1384
+ "Mai Hà",
1385
+ "Mai Hương",
1386
+ "Mai Hạ",
1387
+ "Mai Khanh",
1388
+ "Mai Khôi",
1389
+ "Mai Lan",
1390
+ "Mai Linh",
1391
+ "Mai Liên",
1392
+ "Mai Loan",
1393
+ "Mai Ly",
1394
+ "Mai Nhi",
1395
+ "Mai Phương",
1396
+ "Mai Quyên",
1397
+ "Mai Thanh",
1398
+ "Mai Thu",
1399
+ "Mai Thy",
1400
+ "Mai Thảo",
1401
+ "Mai Trinh",
1402
+ "Mai Tâm",
1403
+ "Mai Vy",
1404
+ "Minh An",
1405
+ "Minh Châu",
1406
+ "Minh Duyên",
1407
+ "Minh Hiền",
1408
+ "Minh Huyền",
1409
+ "Minh Huệ",
1410
+ "Minh Hà",
1411
+ "Minh Hương",
1412
+ "Minh Hạnh",
1413
+ "Minh Hằng",
1414
+ "Minh Hồng",
1415
+ "Minh Khai",
1416
+ "Minh Khuê",
1417
+ "Minh Loan",
1418
+ "Minh Minh",
1419
+ "Minh Nguyệt",
1420
+ "Minh Ngọc",
1421
+ "Minh Nhi",
1422
+ "Minh Như",
1423
+ "Minh Phương",
1424
+ "Minh Phượng",
1425
+ "Minh Thu",
1426
+ "Minh Thúy",
1427
+ "Minh Thư",
1428
+ "Minh Thương",
1429
+ "Minh Thảo",
1430
+ "Minh Thủy",
1431
+ "Minh Trang",
1432
+ "Minh Tuyết",
1433
+ "Minh Tuệ",
1434
+ "Minh Tâm",
1435
+ "Minh Uyên",
1436
+ "Minh Vy",
1437
+ "Minh Xuân",
1438
+ "Minh Yến",
1439
+ "Minh Đan",
1440
+ "Mậu Xuân",
1441
+ "Mộc Miên",
1442
+ "Mộng Hoa",
1443
+ "Mộng Hương",
1444
+ "Mộng Hằng",
1445
+ "Mộng Lan",
1446
+ "Mộng Liễu",
1447
+ "Mộng Nguyệt",
1448
+ "Mộng Nhi",
1449
+ "Mộng Quỳnh",
1450
+ "Mộng Thi",
1451
+ "Mộng Thu",
1452
+ "Mộng Tuyền",
1453
+ "Mộng Vi",
1454
+ "Mộng Vy",
1455
+ "Mộng Vân",
1456
+ "Mộng Ðiệp",
1457
+ "Mỹ Anh",
1458
+ "Mỹ Diễm",
1459
+ "Mỹ Dung",
1460
+ "Mỹ Duyên",
1461
+ "Mỹ Hiệp",
1462
+ "Mỹ Hoàn",
1463
+ "Mỹ Huyền",
1464
+ "Mỹ Huệ",
1465
+ "Mỹ Hường",
1466
+ "Mỹ Hạnh",
1467
+ "Mỹ Khuyên",
1468
+ "Mỹ Kiều",
1469
+ "Mỹ Lan",
1470
+ "Mỹ Loan",
1471
+ "Mỹ Lệ",
1472
+ "Mỹ Lợi",
1473
+ "Mỹ Nga",
1474
+ "Mỹ Ngọc",
1475
+ "Mỹ Nhi",
1476
+ "Mỹ Nhân",
1477
+ "Mỹ Nương",
1478
+ "Mỹ Phương",
1479
+ "Mỹ Phượng",
1480
+ "Mỹ Phụng",
1481
+ "Mỹ Thuần",
1482
+ "Mỹ Thuận",
1483
+ "Mỹ Trang",
1484
+ "Mỹ Trâm",
1485
+ "Mỹ Tâm",
1486
+ "Mỹ Uyên",
1487
+ "Mỹ Vân",
1488
+ "Mỹ Xuân",
1489
+ "Mỹ Yến",
1490
+ "Nghi Dung",
1491
+ "Nghi Minh",
1492
+ "Nghi Xuân",
1493
+ "Nguyên Hồng",
1494
+ "Nguyên Thảo",
1495
+ "Nguyết Ánh",
1496
+ "Nguyệt Anh",
1497
+ "Nguyệt Cát",
1498
+ "Nguyệt Cầm",
1499
+ "Nguyệt Hà",
1500
+ "Nguyệt Hồng",
1501
+ "Nguyệt Lan",
1502
+ "Nguyệt Minh",
1503
+ "Nguyệt Nga",
1504
+ "Nguyệt Quế",
1505
+ "Nguyệt Uyển",
1506
+ "Nguyệt Ánh",
1507
+ "Ngân Anh",
1508
+ "Ngân Hà",
1509
+ "Ngân Thanh",
1510
+ "Ngân Trúc",
1511
+ "Ngọc Anh",
1512
+ "Ngọc Bích",
1513
+ "Ngọc Cầm",
1514
+ "Ngọc Diệp",
1515
+ "Ngọc Dung",
1516
+ "Ngọc Hiền",
1517
+ "Ngọc Hoa",
1518
+ "Ngọc Hoan",
1519
+ "Ngọc Hoàn",
1520
+ "Ngọc Huyền",
1521
+ "Ngọc Huệ",
1522
+ "Ngọc Hà",
1523
+ "Ngọc Hân",
1524
+ "Ngọc Hạ",
1525
+ "Ngọc Hạnh",
1526
+ "Ngọc Hằng",
1527
+ "Ngọc Khanh",
1528
+ "Ngọc Khuê",
1529
+ "Ngọc Khánh",
1530
+ "Ngọc Lam",
1531
+ "Ngọc Lan",
1532
+ "Ngọc Linh",
1533
+ "Ngọc Liên",
1534
+ "Ngọc Loan",
1535
+ "Ngọc Ly",
1536
+ "Ngọc Lâm",
1537
+ "Ngọc Lý",
1538
+ "Ngọc Lệ",
1539
+ "Ngọc Mai",
1540
+ "Ngọc Nhi",
1541
+ "Ngọc Nữ",
1542
+ "Ngọc Oanh",
1543
+ "Ngọc Phụng",
1544
+ "Ngọc Quyên",
1545
+ "Ngọc Quế",
1546
+ "Ngọc Quỳnh",
1547
+ "Ngọc San",
1548
+ "Ngọc Sương",
1549
+ "Ngọc Thi",
1550
+ "Ngọc Thy",
1551
+ "Ngọc Thơ",
1552
+ "Ngọc Trinh",
1553
+ "Ngọc Trâm",
1554
+ "Ngọc Tuyết",
1555
+ "Ngọc Tâm",
1556
+ "Ngọc Tú",
1557
+ "Ngọc Uyên",
1558
+ "Ngọc Uyển",
1559
+ "Ngọc Vy",
1560
+ "Ngọc Vân",
1561
+ "Ngọc Yến",
1562
+ "Ngọc Ái",
1563
+ "Ngọc Ánh",
1564
+ "Ngọc Ðiệp",
1565
+ "Ngọc Ðàn",
1566
+ "Ngọc Ðào",
1567
+ "Nhan Hồng",
1568
+ "Nhã Hương",
1569
+ "Nhã Hồng",
1570
+ "Nhã Khanh",
1571
+ "Nhã Lý",
1572
+ "Nhã Mai",
1573
+ "Nhã Sương",
1574
+ "Nhã Thanh",
1575
+ "Nhã Trang",
1576
+ "Nhã Trúc",
1577
+ "Nhã Uyên",
1578
+ "Nhã Yến",
1579
+ "Nhã Ý",
1580
+ "Như Anh",
1581
+ "Như Bảo",
1582
+ "Như Hoa",
1583
+ "Như Hảo",
1584
+ "Như Hồng",
1585
+ "Như Loan",
1586
+ "Như Mai",
1587
+ "Như Ngà",
1588
+ "Như Ngọc",
1589
+ "Như Phương",
1590
+ "Như Quân",
1591
+ "Như Quỳnh",
1592
+ "Như Thảo",
1593
+ "Như Trân",
1594
+ "Như Tâm",
1595
+ "Như Ý",
1596
+ "Nhất Thương",
1597
+ "Nhật Dạ",
1598
+ "Nhật Hà",
1599
+ "Nhật Hạ",
1600
+ "Nhật Lan",
1601
+ "Nhật Linh",
1602
+ "Nhật Lệ",
1603
+ "Nhật Mai",
1604
+ "Nhật Phương",
1605
+ "Nhật Ánh",
1606
+ "Oanh Thơ",
1607
+ "Oanh Vũ",
1608
+ "Phi Khanh",
1609
+ "Phi Nhung",
1610
+ "Phi Nhạn",
1611
+ "Phi Phi",
1612
+ "Phi Phượng",
1613
+ "Phong Lan",
1614
+ "Phương An",
1615
+ "Phương Anh",
1616
+ "Phương Chi",
1617
+ "Phương Châu",
1618
+ "Phương Diễm",
1619
+ "Phương Dung",
1620
+ "Phương Giang",
1621
+ "Phương Hiền",
1622
+ "Phương Hoa",
1623
+ "Phương Hạnh",
1624
+ "Phương Lan",
1625
+ "Phương Linh",
1626
+ "Phương Liên",
1627
+ "Phương Loan",
1628
+ "Phương Mai",
1629
+ "Phương Nghi",
1630
+ "Phương Ngọc",
1631
+ "Phương Nhi",
1632
+ "Phương Nhung",
1633
+ "Phương Phương",
1634
+ "Phương Quyên",
1635
+ "Phương Quân",
1636
+ "Phương Quế",
1637
+ "Phương Quỳnh",
1638
+ "Phương Thanh",
1639
+ "Phương Thi",
1640
+ "Phương Thùy",
1641
+ "Phương Thảo",
1642
+ "Phương Thủy",
1643
+ "Phương Trang",
1644
+ "Phương Trinh",
1645
+ "Phương Trà",
1646
+ "Phương Trâm",
1647
+ "Phương Tâm",
1648
+ "Phương Uyên",
1649
+ "Phương Yến",
1650
+ "Phước Bình",
1651
+ "Phước Huệ",
1652
+ "Phượng Bích",
1653
+ "Phượng Liên",
1654
+ "Phượng Loan",
1655
+ "Phượng Lệ",
1656
+ "Phượng Nga",
1657
+ "Phượng Nhi",
1658
+ "Phượng Tiên",
1659
+ "Phượng Uyên",
1660
+ "Phượng Vy",
1661
+ "Phượng Vũ",
1662
+ "Phụng Yến",
1663
+ "Quế Anh",
1664
+ "Quế Chi",
1665
+ "Quế Linh",
1666
+ "Quế Lâm",
1667
+ "Quế Phương",
1668
+ "Quế Thu",
1669
+ "Quỳnh Anh",
1670
+ "Quỳnh Chi",
1671
+ "Quỳnh Dao",
1672
+ "Quỳnh Dung",
1673
+ "Quỳnh Giang",
1674
+ "Quỳnh Giao",
1675
+ "Quỳnh Hoa",
1676
+ "Quỳnh Hà",
1677
+ "Quỳnh Hương",
1678
+ "Quỳnh Lam",
1679
+ "Quỳnh Liên",
1680
+ "Quỳnh Lâm",
1681
+ "Quỳnh Nga",
1682
+ "Quỳnh Ngân",
1683
+ "Quỳnh Nhi",
1684
+ "Quỳnh Nhung",
1685
+ "Quỳnh Như",
1686
+ "Quỳnh Phương",
1687
+ "Quỳnh Sa",
1688
+ "Quỳnh Thanh",
1689
+ "Quỳnh Thơ",
1690
+ "Quỳnh Tiên",
1691
+ "Quỳnh Trang",
1692
+ "Quỳnh Trâm",
1693
+ "Quỳnh Vân",
1694
+ "Sao Băng",
1695
+ "Sao Mai",
1696
+ "Song Kê",
1697
+ "Song Lam",
1698
+ "Song Oanh",
1699
+ "Song Thư",
1700
+ "Sông Hà",
1701
+ "Sông Hương",
1702
+ "Sơn Ca",
1703
+ "Sơn Tuyền",
1704
+ "Sương Sương",
1705
+ "Thanh Bình",
1706
+ "Thanh Dân",
1707
+ "Thanh Giang",
1708
+ "Thanh Hiếu",
1709
+ "Thanh Hiền",
1710
+ "Thanh Hoa",
1711
+ "Thanh Huyền",
1712
+ "Thanh Hà",
1713
+ "Thanh Hương",
1714
+ "Thanh Hường",
1715
+ "Thanh Hạnh",
1716
+ "Thanh Hảo",
1717
+ "Thanh Hằng",
1718
+ "Thanh Hồng",
1719
+ "Thanh Kiều",
1720
+ "Thanh Lam",
1721
+ "Thanh Lan",
1722
+ "Thanh Loan",
1723
+ "Thanh Lâm",
1724
+ "Thanh Mai",
1725
+ "Thanh Mẫn",
1726
+ "Thanh Nga",
1727
+ "Thanh Nguyên",
1728
+ "Thanh Ngân",
1729
+ "Thanh Ngọc",
1730
+ "Thanh Nhung",
1731
+ "Thanh Nhàn",
1732
+ "Thanh Nhã",
1733
+ "Thanh Phương",
1734
+ "Thanh Thanh",
1735
+ "Thanh Thiên",
1736
+ "Thanh Thu",
1737
+ "Thanh Thúy",
1738
+ "Thanh Thư",
1739
+ "Thanh Thảo",
1740
+ "Thanh Thủy",
1741
+ "Thanh Trang",
1742
+ "Thanh Trúc",
1743
+ "Thanh Tuyết",
1744
+ "Thanh Tuyền",
1745
+ "Thanh Tâm",
1746
+ "Thanh Uyên",
1747
+ "Thanh Vy",
1748
+ "Thanh Vân",
1749
+ "Thanh Xuân",
1750
+ "Thanh Yến",
1751
+ "Thanh Đan",
1752
+ "Thi Cầm",
1753
+ "Thi Ngôn",
1754
+ "Thi Thi",
1755
+ "Thi Xuân",
1756
+ "Thi Yến",
1757
+ "Thiên Di",
1758
+ "Thiên Duyên",
1759
+ "Thiên Giang",
1760
+ "Thiên Hà",
1761
+ "Thiên Hương",
1762
+ "Thiên Khánh",
1763
+ "Thiên Kim",
1764
+ "Thiên Lam",
1765
+ "Thiên Lan",
1766
+ "Thiên Mai",
1767
+ "Thiên Mỹ",
1768
+ "Thiên Nga",
1769
+ "Thiên Nương",
1770
+ "Thiên Phương",
1771
+ "Thiên Thanh",
1772
+ "Thiên Thêu",
1773
+ "Thiên Thư",
1774
+ "Thiên Thảo",
1775
+ "Thiên Trang",
1776
+ "Thiên Tuyền",
1777
+ "Thiếu Mai",
1778
+ "Thiều Ly",
1779
+ "Thiện Mỹ",
1780
+ "Thiện Tiên",
1781
+ "Thu Duyên",
1782
+ "Thu Giang",
1783
+ "Thu Hiền",
1784
+ "Thu Hoài",
1785
+ "Thu Huyền",
1786
+ "Thu Huệ",
1787
+ "Thu Hà",
1788
+ "Thu Hậu",
1789
+ "Thu Hằng",
1790
+ "Thu Hồng",
1791
+ "Thu Linh",
1792
+ "Thu Liên",
1793
+ "Thu Loan",
1794
+ "Thu Mai",
1795
+ "Thu Minh",
1796
+ "Thu Nga",
1797
+ "Thu Nguyệt",
1798
+ "Thu Ngà",
1799
+ "Thu Ngân",
1800
+ "Thu Ngọc",
1801
+ "Thu Nhiên",
1802
+ "Thu Oanh",
1803
+ "Thu Phong",
1804
+ "Thu Phương",
1805
+ "Thu Phượng",
1806
+ "Thu Sương",
1807
+ "Thu Thuận",
1808
+ "Thu Thảo",
1809
+ "Thu Thủy",
1810
+ "Thu Trang",
1811
+ "Thu Việt",
1812
+ "Thu Vân",
1813
+ "Thu Vọng",
1814
+ "Thu Yến",
1815
+ "Thuần Hậu",
1816
+ "Thy Khanh",
1817
+ "Thy Oanh",
1818
+ "Thy Trúc",
1819
+ "Thy Vân",
1820
+ "Thái Chi",
1821
+ "Thái Hà",
1822
+ "Thái Hồng",
1823
+ "Thái Lan",
1824
+ "Thái Lâm",
1825
+ "Thái Thanh",
1826
+ "Thái Thảo",
1827
+ "Thái Tâm",
1828
+ "Thái Vân",
1829
+ "Thùy Anh",
1830
+ "Thùy Dung",
1831
+ "Thùy Dương",
1832
+ "Thùy Giang",
1833
+ "Thùy Linh",
1834
+ "Thùy Mi",
1835
+ "Thùy My",
1836
+ "Thùy Nhi",
1837
+ "Thùy Như",
1838
+ "Thùy Oanh",
1839
+ "Thùy Uyên",
1840
+ "Thùy Vân",
1841
+ "Thúy Anh",
1842
+ "Thúy Diễm",
1843
+ "Thúy Hiền",
1844
+ "Thúy Huyền",
1845
+ "Thúy Hà",
1846
+ "Thúy Hương",
1847
+ "Thúy Hường",
1848
+ "Thúy Hạnh",
1849
+ "Thúy Hằng",
1850
+ "Thúy Kiều",
1851
+ "Thúy Liên",
1852
+ "Thúy Liễu",
1853
+ "Thúy Loan",
1854
+ "Thúy Mai",
1855
+ "Thúy Minh",
1856
+ "Thúy My",
1857
+ "Thúy Nga",
1858
+ "Thúy Ngà",
1859
+ "Thúy Ngân",
1860
+ "Thúy Ngọc",
1861
+ "Thúy Phượng",
1862
+ "Thúy Quỳnh",
1863
+ "Thúy Vi",
1864
+ "Thúy Vy",
1865
+ "Thúy Vân",
1866
+ "Thơ Thơ",
1867
+ "Thư Lâm",
1868
+ "Thư Sương",
1869
+ "Thương Huyền",
1870
+ "Thương Nga",
1871
+ "Thương Thương",
1872
+ "Thường Xuân",
1873
+ "Thạch Thảo",
1874
+ "Thảo Hương",
1875
+ "Thảo Hồng",
1876
+ "Thảo Linh",
1877
+ "Thảo Ly",
1878
+ "Thảo Mai",
1879
+ "Thảo My",
1880
+ "Thảo Nghi",
1881
+ "Thảo Nguyên",
1882
+ "Thảo Nhi",
1883
+ "Thảo Quyên",
1884
+ "Thảo Tiên",
1885
+ "Thảo Trang",
1886
+ "Thảo Uyên",
1887
+ "Thảo Vy",
1888
+ "Thảo Vân",
1889
+ "Thục Anh",
1890
+ "Thục Khuê",
1891
+ "Thục Nhi",
1892
+ "Thục Oanh",
1893
+ "Thục Quyên",
1894
+ "Thục Trang",
1895
+ "Thục Trinh",
1896
+ "Thục Tâm",
1897
+ "Thục Uyên",
1898
+ "Thục Vân",
1899
+ "Thục Ðoan",
1900
+ "Thục Ðào",
1901
+ "Thục Ðình",
1902
+ "Thụy Du",
1903
+ "Thụy Khanh",
1904
+ "Thụy Linh",
1905
+ "Thụy Lâm",
1906
+ "Thụy Miên",
1907
+ "Thụy Nương",
1908
+ "Thụy Trinh",
1909
+ "Thụy Trâm",
1910
+ "Thụy Uyên",
1911
+ "Thụy Vân",
1912
+ "Thụy Ðào",
1913
+ "Thủy Hằng",
1914
+ "Thủy Hồng",
1915
+ "Thủy Linh",
1916
+ "Thủy Minh",
1917
+ "Thủy Nguyệt",
1918
+ "Thủy Quỳnh",
1919
+ "Thủy Tiên",
1920
+ "Thủy Trang",
1921
+ "Thủy Tâm",
1922
+ "Tinh Tú",
1923
+ "Tiên Phương",
1924
+ "Tiểu Mi",
1925
+ "Tiểu My",
1926
+ "Tiểu Quỳnh",
1927
+ "Trang Anh",
1928
+ "Trang Linh",
1929
+ "Trang Nhã",
1930
+ "Trang Tâm",
1931
+ "Trang Ðài",
1932
+ "Triều Nguyệt",
1933
+ "Triều Thanh",
1934
+ "Triệu Mẫn",
1935
+ "Trung Anh",
1936
+ "Trà Giang",
1937
+ "Trà My",
1938
+ "Trâm Anh",
1939
+ "Trâm Oanh",
1940
+ "Trân Châu",
1941
+ "Trúc Chi",
1942
+ "Trúc Lam",
1943
+ "Trúc Lan",
1944
+ "Trúc Linh",
1945
+ "Trúc Liên",
1946
+ "Trúc Loan",
1947
+ "Trúc Ly",
1948
+ "Trúc Lâm",
1949
+ "Trúc Mai",
1950
+ "Trúc Phương",
1951
+ "Trúc Quân",
1952
+ "Trúc Quỳnh",
1953
+ "Trúc Vy",
1954
+ "Trúc Vân",
1955
+ "Trúc Ðào",
1956
+ "Trúc Đào",
1957
+ "Trầm Hương",
1958
+ "Tuyết Anh",
1959
+ "Tuyết Băng",
1960
+ "Tuyết Chi",
1961
+ "Tuyết Hoa",
1962
+ "Tuyết Hân",
1963
+ "Tuyết Hương",
1964
+ "Tuyết Hồng",
1965
+ "Tuyết Lan",
1966
+ "Tuyết Loan",
1967
+ "Tuyết Lâm",
1968
+ "Tuyết Mai",
1969
+ "Tuyết Nga",
1970
+ "Tuyết Nhi",
1971
+ "Tuyết Nhung",
1972
+ "Tuyết Oanh",
1973
+ "Tuyết Thanh",
1974
+ "Tuyết Trinh",
1975
+ "Tuyết Trầm",
1976
+ "Tuyết Tâm",
1977
+ "Tuyết Vy",
1978
+ "Tuyết Vân",
1979
+ "Tuyết Xuân",
1980
+ "Tuyền Lâm",
1981
+ "Tuệ Lâm",
1982
+ "Tuệ Mẫn",
1983
+ "Tuệ Nhi",
1984
+ "Tâm Hiền",
1985
+ "Tâm Hạnh",
1986
+ "Tâm Hằng",
1987
+ "Tâm Khanh",
1988
+ "Tâm Linh",
1989
+ "Tâm Nguyên",
1990
+ "Tâm Nguyệt",
1991
+ "Tâm Nhi",
1992
+ "Tâm Như",
1993
+ "Tâm Thanh",
1994
+ "Tâm Trang",
1995
+ "Tâm Ðoan",
1996
+ "Tâm Đan",
1997
+ "Tùng Linh",
1998
+ "Tùng Lâm",
1999
+ "Tùng Quân",
2000
+ "Tùy Anh",
2001
+ "Tùy Linh",
2002
+ "Tú Anh",
2003
+ "Tú Ly",
2004
+ "Tú Nguyệt",
2005
+ "Tú Quyên",
2006
+ "Tú Quỳnh",
2007
+ "Tú Sương",
2008
+ "Tú Trinh",
2009
+ "Tú Tâm",
2010
+ "Tú Uyên",
2011
+ "Túy Loan",
2012
+ "Tường Chinh",
2013
+ "Tường Vi",
2014
+ "Tường Vy",
2015
+ "Tường Vân",
2016
+ "Tịnh Lâm",
2017
+ "Tịnh Nhi",
2018
+ "Tịnh Như",
2019
+ "Tịnh Tâm",
2020
+ "Tịnh Yên",
2021
+ "Tố Loan",
2022
+ "Tố Nga",
2023
+ "Tố Nhi",
2024
+ "Tố Quyên",
2025
+ "Tố Tâm",
2026
+ "Tố Uyên",
2027
+ "Từ Dung",
2028
+ "Từ Ân",
2029
+ "Uyên Minh",
2030
+ "Uyên My",
2031
+ "Uyên Nhi",
2032
+ "Uyên Phương",
2033
+ "Uyên Thi",
2034
+ "Uyên Thy",
2035
+ "Uyên Thơ",
2036
+ "Uyên Trâm",
2037
+ "Uyên Vi",
2038
+ "Uyển Khanh",
2039
+ "Uyển My",
2040
+ "Uyển Nghi",
2041
+ "Uyển Nhi",
2042
+ "Uyển Nhã",
2043
+ "Uyển Như",
2044
+ "Vi Quyên",
2045
+ "Vinh Diệu",
2046
+ "Việt Hà",
2047
+ "Việt Hương",
2048
+ "Việt Khuê",
2049
+ "Việt Mi",
2050
+ "Việt Nga",
2051
+ "Việt Nhi",
2052
+ "Việt Thi",
2053
+ "Việt Trinh",
2054
+ "Việt Tuyết",
2055
+ "Việt Yến",
2056
+ "Vy Lam",
2057
+ "Vy Lan",
2058
+ "Vàng Anh",
2059
+ "Vành Khuyên",
2060
+ "Vân Anh",
2061
+ "Vân Chi",
2062
+ "Vân Du",
2063
+ "Vân Hà",
2064
+ "Vân Hương",
2065
+ "Vân Khanh",
2066
+ "Vân Khánh",
2067
+ "Vân Linh",
2068
+ "Vân Ngọc",
2069
+ "Vân Nhi",
2070
+ "Vân Phi",
2071
+ "Vân Phương",
2072
+ "Vân Quyên",
2073
+ "Vân Quỳnh",
2074
+ "Vân Thanh",
2075
+ "Vân Thúy",
2076
+ "Vân Thường",
2077
+ "Vân Tiên",
2078
+ "Vân Trang",
2079
+ "Vân Trinh",
2080
+ "Vũ Hồng",
2081
+ "Xuyến Chi",
2082
+ "Xuân Bảo",
2083
+ "Xuân Dung",
2084
+ "Xuân Hiền",
2085
+ "Xuân Hoa",
2086
+ "Xuân Hân",
2087
+ "Xuân Hương",
2088
+ "Xuân Hạnh",
2089
+ "Xuân Lan",
2090
+ "Xuân Linh",
2091
+ "Xuân Liễu",
2092
+ "Xuân Loan",
2093
+ "Xuân Lâm",
2094
+ "Xuân Mai",
2095
+ "Xuân Nghi",
2096
+ "Xuân Ngọc",
2097
+ "Xuân Nhi",
2098
+ "Xuân Nhiên",
2099
+ "Xuân Nương",
2100
+ "Xuân Phương",
2101
+ "Xuân Phượng",
2102
+ "Xuân Thanh",
2103
+ "Xuân Thu",
2104
+ "Xuân Thảo",
2105
+ "Xuân Thủy",
2106
+ "Xuân Trang",
2107
+ "Xuân Tâm",
2108
+ "Xuân Uyên",
2109
+ "Xuân Vân",
2110
+ "Xuân Yến",
2111
+ "Xuân xanh",
2112
+ "Yên Bằng",
2113
+ "Yên Mai",
2114
+ "Yên Nhi",
2115
+ "Yên Ðan",
2116
+ "Yên Đan",
2117
+ "Yến Anh",
2118
+ "Yến Hồng",
2119
+ "Yến Loan",
2120
+ "Yến Mai",
2121
+ "Yến My",
2122
+ "Yến Nhi",
2123
+ "Yến Oanh",
2124
+ "Yến Phương",
2125
+ "Yến Phượng",
2126
+ "Yến Thanh",
2127
+ "Yến Thảo",
2128
+ "Yến Trang",
2129
+ "Yến Trinh",
2130
+ "Yến Trâm",
2131
+ "Yến Ðan",
2132
+ "Ái Hồng",
2133
+ "Ái Khanh",
2134
+ "Ái Linh",
2135
+ "Ái Nhi",
2136
+ "Ái Nhân",
2137
+ "Ái Thi",
2138
+ "Ái Thy",
2139
+ "Ái Vân",
2140
+ "Ánh Dương",
2141
+ "Ánh Hoa",
2142
+ "Ánh Hồng",
2143
+ "Ánh Linh",
2144
+ "Ánh Lệ",
2145
+ "Ánh Mai",
2146
+ "Ánh Nguyệt",
2147
+ "Ánh Ngọc",
2148
+ "Ánh Thơ",
2149
+ "Ánh Trang",
2150
+ "Ánh Tuyết",
2151
+ "Ánh Xuân",
2152
+ "Ðan Khanh",
2153
+ "Ðan Quỳnh",
2154
+ "Ðan Thu",
2155
+ "Ðinh Hương",
2156
+ "Ðoan Thanh",
2157
+ "Ðoan Trang",
2158
+ "Ðài Trang",
2159
+ "Ðông Nghi",
2160
+ "Ðông Nhi",
2161
+ "Ðông Trà",
2162
+ "Ðông Tuyền",
2163
+ "Ðông Vy",
2164
+ "Ðông Ðào",
2165
+ "Ðồng Dao",
2166
+ "Ý Bình",
2167
+ "Ý Lan",
2168
+ "Ý Nhi",
2169
+ "Đan Linh",
2170
+ "Đan Quỳnh",
2171
+ "Đan Thanh",
2172
+ "Đan Thu",
2173
+ "Đan Thư",
2174
+ "Đan Tâm",
2175
+ "Đinh Hương",
2176
+ "Đoan Thanh",
2177
+ "Đoan Trang",
2178
+ "Đài Trang",
2179
+ "Đông Nghi",
2180
+ "Đông Trà",
2181
+ "Đông Tuyền",
2182
+ "Đông Vy",
2183
+ "Đơn Thuần",
2184
+ "Đức Hạnh",
2185
+ "Ấu Lăng"
2186
+ ]
2187
+ let OtherName = [".",",","/","%", "&","*","-","+"];
2188
+ try {
2189
+ var Name;
2190
+ if (name == " " || name == null) return "UNKNOWN";
2191
+ switch (female_name.some(a => name.includes(a))) {
2192
+ case true: {
2193
+ if (!OtherName.includes(name)) Name = "FEMALE";
2194
+ else Name = ['FEMALE','MALE'][Math.floor(Math.random() * 2)]; // just temp 🌚
2195
+ }
2196
+ break;
2197
+ case false: {
2198
+ if (female_name.some(a => name.split(' ')[name.split(' ').length - 1] == a)) Name = "FEMALE";
2199
+ else if (!OtherName.includes(name) && !female_name.includes(name)) Name = "MALE";
2200
+ else Name = ['FEMALE','MALE'][Math.floor(Math.random() * 2)]; // just temp 🌚
2201
+ }
2202
+ break;
2203
+ }
2204
+ }
2205
+ catch (e) {
2206
+ return "UNKNOWN";
2207
+ }
2208
+ return Name || "UNKNOWN";
2209
+ }
2210
+
2211
+ /**
2212
+ * @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
2213
+ */
2214
+
2215
+ function formatDeltaEvent(m) {
2216
+ var { updateData,getData,hasData } = require('./Extra/ExtraGetThread');
2217
+ var logMessageType;
2218
+ var logMessageData;
2219
+
2220
+ switch (m.class) {
2221
+ case "AdminTextMessage":
2222
+ logMessageType = getAdminTextMessageType(m);
2223
+ logMessageData = m.untypedData;
2224
+ break;
2225
+ case "ThreadName":
2226
+ logMessageType = "log:thread-name";
2227
+ logMessageData = { name: m.name };
2228
+ break;
2229
+ case "ParticipantsAddedToGroupThread":
2230
+ logMessageType = "log:subscribe";
2231
+ logMessageData = { addedParticipants: m.addedParticipants };
2232
+ break;
2233
+ case "ParticipantLeftGroupThread":
2234
+ logMessageType = "log:unsubscribe";
2235
+ logMessageData = { leftParticipantFbId: m.leftParticipantFbId };
2236
+ break;
2237
+ case "UserLocation": {
2238
+ logMessageType = "log:user-location";
2239
+ logMessageData = {
2240
+ Image: m.attachments[0].mercury.extensible_attachment.story_attachment.media.image,
2241
+ Location: m.attachments[0].mercury.extensible_attachment.story_attachment.target.location_title,
2242
+ coordinates: m.attachments[0].mercury.extensible_attachment.story_attachment.target.coordinate,
2243
+ url: m.attachments[0].mercury.extensible_attachment.story_attachment.url
2244
+ };
2245
+ }
2246
+ }
2247
+ switch (hasData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()))) {
2248
+ case true: {
2249
+ switch (logMessageType) {
2250
+ case "log:thread-color": {
2251
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2252
+ x.emoji = (logMessageData.theme_emoji || x.emoji);
2253
+ x.color = (logMessageData['theme_color'] || x.color);
2254
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
2255
+ }
2256
+ break;
2257
+ case "log:thread-icon": {
2258
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2259
+ x.emoji = (logMessageData['thread_icon'] || x.emoji);
2260
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
2261
+ }
2262
+ break;
2263
+ case "log:user-nickname": {
2264
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2265
+ x.nicknames[logMessageData.participant_id] = (logMessageData.nickname.length == 0 ? x.userInfo.find(i => i.id == String(logMessageData.participant_id)).name : logMessageData.nickname);
2266
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
2267
+ }
2268
+ break;
2269
+ case "log:thread-admins": {
2270
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2271
+ switch (logMessageData.ADMIN_EVENT) {
2272
+ case "add_admin": {
2273
+ x.adminIDs.push({ id: logMessageData.TARGET_ID });
2274
+ }
2275
+ break;
2276
+ case "remove_admin": {
2277
+ x.adminIDs = x.adminIDs.filter(item => item.id != logMessageData.TARGET_ID);
2278
+ }
2279
+ break;
2280
+ }
2281
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
2282
+ }
2283
+ break;
2284
+ case "log:thread-approval-mode": {
2285
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2286
+ if (x.approvalMode == true) {
2287
+ x.approvalMode = false;
2288
+ }
2289
+ else {
2290
+ x.approvalMode = true;
2291
+ }
2292
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
2293
+ }
2294
+ break;
2295
+ case "log:thread-name": {
2296
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2297
+ x.threadName = (logMessageData.name || formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2298
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
2299
+ }
2300
+ break;
2301
+ case "log:subscribe": {
2302
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2303
+ for (let o of logMessageData.addedParticipants) {
2304
+ if (x.userInfo.some(i => i.id == o.userFbId)) continue;
2305
+ else {
2306
+ x.userInfo.push({
2307
+ id: o.userFbId,
2308
+ name: o.fullName,
2309
+ gender: getGenderByPhysicalMethod(o.fullName)
2310
+ });
2311
+ x.participantIDs.push(o.userFbId);
2312
+ }
2313
+ }
2314
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
2315
+ }
2316
+ break;
2317
+ case "log:unsubscribe": {
2318
+ let x = getData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()));
2319
+ x.participantIDs = x.participantIDs.filter(item => item != logMessageData.leftParticipantFbId);
2320
+ x.userInfo = x.userInfo.filter(item => item.id != logMessageData.leftParticipantFbId);
2321
+ if (x.adminIDs.some(i => i.id == logMessageData.leftParticipantFbId)) {
2322
+ x.adminIDs = x.adminIDs.filter(item => item.id != logMessageData.leftParticipantFbId);
2323
+ }
2324
+ updateData(formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),x);
2325
+ }
2326
+ break;
2327
+ }
2328
+ }
2329
+ }
2330
+
2331
+ return {
2332
+ type: "event",
2333
+ threadID: formatID((m.messageMetadata.threadKey.threadFbId || m.messageMetadata.threadKey.otherUserFbId).toString()),
2334
+ logMessageType: logMessageType,
2335
+ logMessageData: logMessageData,
2336
+ logMessageBody: m.messageMetadata.adminText,
2337
+ author: m.messageMetadata.actorFbId,
2338
+ participantIDs: m.participants || []
2339
+ };
2340
+ }
2341
+
2342
+ /**
2343
+ * @param {{ st: any; from: { toString: () => any; }; to: any; thread_fbid: any; hasOwnProperty: (arg0: string) => any; from_mobile: any; realtime_viewer_fbid: any; }} event
2344
+ */
2345
+
2346
+ function formatTyp(event) {
2347
+ return {
2348
+ isTyping: !!event.st,
2349
+ from: event.from.toString(),
2350
+ threadID: formatID((event.to || event.thread_fbid || event.from).toString()),
2351
+ // When receiving typ indication from mobile, `from_mobile` isn't set.
2352
+ // If it is, we just use that value.
2353
+ fromMobile: event.hasOwnProperty("from_mobile") ? event.from_mobile : true,
2354
+ userID: (event.realtime_viewer_fbid || event.from).toString(),
2355
+ type: "typ"
2356
+ };
2357
+ }
2358
+
2359
+ /**
2360
+ * @param {{ threadKey: { otherUserFbId: any; threadFbId: any; }; actorFbId: any; actionTimestampMs: any; }} delta
2361
+ */
2362
+
2363
+ function formatDeltaReadReceipt(delta) {
2364
+ // otherUserFbId seems to be used as both the readerID and the threadID in a 1-1 chat.
2365
+ // In a group chat actorFbId is used for the reader and threadFbId for the thread.
2366
+ return {
2367
+ reader: (delta.threadKey.otherUserFbId || delta.actorFbId).toString(),
2368
+ time: delta.actionTimestampMs,
2369
+ threadID: formatID((delta.threadKey.otherUserFbId || delta.threadKey.threadFbId).toString()),
2370
+ type: "read_receipt"
2371
+ };
2372
+ }
2373
+
2374
+ /**
2375
+ * @param {{ reader: { toString: () => any; }; time: any; thread_fbid: any; }} event
2376
+ */
2377
+
2378
+ function formatReadReceipt(event) {
2379
+ return {
2380
+ reader: event.reader.toString(),
2381
+ time: event.time,
2382
+ threadID: formatID((event.thread_fbid || event.reader).toString()),
2383
+ type: "read_receipt"
2384
+ };
2385
+ }
2386
+
2387
+ /**
2388
+ * @param {{ chat_ids: any[]; thread_fbids: any[]; timestamp: any; }} event
2389
+ */
2390
+
2391
+ function formatRead(event) {
2392
+ return {
2393
+ threadID: formatID(((event.chat_ids && event.chat_ids[0]) || (event.thread_fbids && event.thread_fbids[0])).toString()),
2394
+ time: event.timestamp,
2395
+ type: "read"
2396
+ };
2397
+ }
2398
+
2399
+ /**
2400
+ * @param {string} str
2401
+ * @param {string | any[]} startToken
2402
+ * @param {string} endToken
2403
+ */
2404
+
2405
+ function getFrom(str, startToken, endToken) {
2406
+ var start = str.indexOf(startToken) + startToken.length;
2407
+ if (start < startToken.length) return "";
2408
+
2409
+ var lastHalf = str.substring(start);
2410
+ var end = lastHalf.indexOf(endToken);
2411
+ if (end === -1) throw Error("Could not find endTime `" + endToken + "` in the given string.");
2412
+ return lastHalf.substring(0, end);
2413
+ }
2414
+
2415
+ /**
2416
+ * @param {string} html
2417
+ */
2418
+
2419
+ function makeParsable(html) {
2420
+ let withoutForLoop = html.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/
2421
+ , "");
2422
+
2423
+ // (What the fuck FB, why windows style newlines?)
2424
+ // So sometimes FB will send us base multiple objects in the same response.
2425
+ // They're all valid JSON, one after the other, at the top level. We detect
2426
+ // that and make it parse-able by JSON.parse.
2427
+ // Ben - July 15th 2017
2428
+ //
2429
+ // It turns out that Facebook may insert random number of spaces before
2430
+ // next object begins (issue #616)
2431
+ // rav_kr - 2018-03-19
2432
+ let maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
2433
+ if (maybeMultipleObjects.length === 1) return maybeMultipleObjects;
2434
+
2435
+ return "[" + maybeMultipleObjects.join("},{") + "]";
2436
+ }
2437
+
2438
+ /**
2439
+ * @param {any} form
2440
+ */
2441
+
2442
+ function arrToForm(form) {
2443
+ return arrayToObject(form,
2444
+ function(/** @type {{ name: any; }} */v) {
2445
+ return v.name;
2446
+ },
2447
+ function(/** @type {{ val: any; }} */v) {
2448
+ return v.val;
2449
+ }
2450
+ );
2451
+ }
2452
+
2453
+ /**
2454
+ * @param {any[]} arr
2455
+ * @param {{ (v: any): any; (arg0: any): string | number; }} getKey
2456
+ * @param {{ (v: any): any; (arg0: any): any; }} getValue
2457
+ */
2458
+
2459
+ function arrayToObject(arr, getKey, getValue) {
2460
+ return arr.reduce(function(/** @type {{ [x: string]: any; }} */
2461
+ acc, /** @type {any} */val) {
2462
+ acc[getKey(val)] = getValue(val);
2463
+ return acc;
2464
+ }, {});
2465
+ }
2466
+
2467
+ function getSignatureID() {
2468
+ return Math.floor(Math.random() * 2147483648).toString(16);
2469
+ }
2470
+
2471
+ function generateTimestampRelative() {
2472
+ var d = new Date();
2473
+ return d.getHours() + ":" + padZeros(d.getMinutes());
2474
+ }
2475
+
2476
+ /**
2477
+ * @param {any} html
2478
+ * @param {any} userID
2479
+ * @param {{ fb_dtsg: any; ttstamp: any; globalOptions: any; }} ctx
2480
+ */
2481
+
2482
+ function makeDefaults(html, userID, ctx) {
2483
+ var reqCounter = 1;
2484
+ var fb_dtsg = getFrom(html, 'name="fb_dtsg" value="', '"');
2485
+
2486
+ // @Hack Ok we've done hacky things, this is definitely on top 5.
2487
+ // We totally assume the object is flat and try parsing until a }.
2488
+ // If it works though it's cool because we get a bunch of extra data things.
2489
+ //
2490
+ // Update: we don't need this. Leaving it in in case we ever do.
2491
+ // Ben - July 15th 2017
2492
+
2493
+ // var siteData = getFrom(html, "[\"SiteData\",[],", "},");
2494
+ // try {
2495
+ // siteData = JSON.parse(siteData + "}");
2496
+ // } catch(e) {
2497
+ // log.warn("makeDefaults", "Couldn't parse SiteData. Won't have access to some variables.");
2498
+ // siteData = {};
2499
+ // }
2500
+
2501
+ var ttstamp = "2";
2502
+ for (var i = 0; i < fb_dtsg.length; i++) ttstamp += fb_dtsg.charCodeAt(i);
2503
+ var revision = getFrom(html, 'revision":', ",");
2504
+
2505
+ /**
2506
+ * @param {{ [x: string]: any; hasOwnProperty: (arg0: string) => any; }} obj
2507
+ */
2508
+
2509
+ function mergeWithDefaults(obj) {
2510
+ // @TODO This is missing a key called __dyn.
2511
+ // After some investigation it seems like __dyn is some sort of set that FB
2512
+ // calls BitMap. It seems like certain responses have a "define" key in the
2513
+ // res.jsmods arrays. I think the code iterates over those and calls `set`
2514
+ // on the bitmap for each of those keys. Then it calls
2515
+ // bitmap.toCompressedString() which returns what __dyn is.
2516
+ //
2517
+ // So far the API has been working without this.
2518
+ //
2519
+ // Ben - July 15th 2017
2520
+ var newObj = {
2521
+ __user: userID,
2522
+ __req: (reqCounter++).toString(36),
2523
+ __rev: revision,
2524
+ __a: 1,
2525
+ // __af: siteData.features,
2526
+ fb_dtsg: ctx.fb_dtsg ? ctx.fb_dtsg : fb_dtsg,
2527
+ jazoest: ctx.ttstamp ? ctx.ttstamp : ttstamp
2528
+ // __spin_r: siteData.__spin_r,
2529
+ // __spin_b: siteData.__spin_b,
2530
+ // __spin_t: siteData.__spin_t,
2531
+ };
2532
+
2533
+ // @TODO this is probably not needed.
2534
+ // Ben - July 15th 2017
2535
+ // if (siteData.be_key) {
2536
+ // newObj[siteData.be_key] = siteData.be_mode;
2537
+ // }
2538
+ // if (siteData.pkg_cohort_key) {
2539
+ // newObj[siteData.pkg_cohort_key] = siteData.pkg_cohort;
2540
+ // }
2541
+
2542
+ if (!obj) return newObj;
2543
+ for (var prop in obj)
2544
+ if (obj.hasOwnProperty(prop))
2545
+ if (!newObj[prop]) newObj[prop] = obj[prop];
2546
+ return newObj;
2547
+ }
2548
+
2549
+ /**
2550
+ * @param {any} url
2551
+ * @param {any} jar
2552
+ * @param {any} form
2553
+ * @param {any} ctxx
2554
+ */
2555
+
2556
+ function postWithDefaults(url, jar, form, ctxx) {
2557
+ return post(url, jar, mergeWithDefaults(form), ctx.globalOptions, ctxx || ctx);
2558
+ }
2559
+
2560
+ /**
2561
+ * @param {any} url
2562
+ * @param {any} jar
2563
+ * @param {any} qs
2564
+ * @param {any} ctxx
2565
+ */
2566
+
2567
+ function getWithDefaults(url, jar, qs, ctxx) {
2568
+ return get(url, jar, mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
2569
+ }
2570
+
2571
+ /**
2572
+ * @param {any} url
2573
+ * @param {any} jar
2574
+ * @param {any} form
2575
+ * @param {any} qs
2576
+ * @param {any} ctxx
2577
+ */
2578
+
2579
+ function postFormDataWithDefault(url, jar, form, qs, ctxx) {
2580
+ return postFormData(url, jar, mergeWithDefaults(form), mergeWithDefaults(qs), ctx.globalOptions, ctxx || ctx);
2581
+ }
2582
+
2583
+ return {
2584
+ get: getWithDefaults,
2585
+ post: postWithDefaults,
2586
+ postFormData: postFormDataWithDefault
2587
+ };
2588
+ }
2589
+
2590
+ /**
2591
+ * @param {{ jar: { setCookie: (arg0: string, arg1: string) => void; }; fb_dtsg: string; ttstamp: string; }} ctx
2592
+ * @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
2593
+ * @param {string | number} [retryCount]
2594
+ */
2595
+
2596
+ function parseAndCheckLogin(ctx, defaultFuncs, retryCount) {
2597
+ if (retryCount == undefined) retryCount = 0;
2598
+ 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) {
2599
+ return bluebird.try(function() {
2600
+ log.verbose("parseAndCheckLogin", data.body);
2601
+ if (data.statusCode >= 500 && data.statusCode < 600) {
2602
+ if (retryCount >= 5) {
2603
+ throw {
2604
+ error: "Request retry failed. Check the `res` and `statusCode` property on this error.",
2605
+ statusCode: data.statusCode,
2606
+ res: data.body
2607
+ };
2608
+ }
2609
+ retryCount++;
2610
+ var retryTime = Math.floor(Math.random() * 5000);
2611
+ log.warn("parseAndCheckLogin", "Got status code " + data.statusCode + " - " + retryCount + ". attempt to retry in " + retryTime + " milliseconds...");
2612
+ var url = data.request.uri.protocol + "//" + data.request.uri.hostname + data.request.uri.pathname;
2613
+ if (data.request.headers["Content-Type"].split(";")[0] === "multipart/form-data") {
2614
+ return bluebird.delay(retryTime).then(() => defaultFuncs.postFormData(url, ctx.jar, data.request.formData, {}))
2615
+ .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
2616
+ } else {
2617
+ return bluebird.delay(retryTime).then(() => defaultFuncs.post(url, ctx.jar, data.request.formData))
2618
+ .then(parseAndCheckLogin(ctx, defaultFuncs, retryCount));
2619
+ }
2620
+ }
2621
+ if (data.statusCode !== 200) throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
2622
+
2623
+ var res = null;
2624
+ try {
2625
+ res = JSON.parse(makeParsable(data.body));
2626
+ } catch (e) {
2627
+ throw {
2628
+ error: "JSON.parse error. Check the `detail` property on this error.",
2629
+ detail: e,
2630
+ res: data.body
2631
+ };
2632
+ }
2633
+
2634
+ // In some cases the response contains only a redirect URL which should be followed
2635
+ if (res.redirect && data.request.method === "GET") return defaultFuncs.get(res.redirect, ctx.jar).then(parseAndCheckLogin(ctx, defaultFuncs));
2636
+
2637
+ // TODO: handle multiple cookies?
2638
+ if (res.jsmods && res.jsmods.require && Array.isArray(res.jsmods.require[0]) && res.jsmods.require[0][0] === "Cookie") {
2639
+ res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
2640
+ var cookie = formatCookie(res.jsmods.require[0][3], "facebook");
2641
+ var cookie2 = formatCookie(res.jsmods.require[0][3], "messenger");
2642
+ ctx.jar.setCookie(cookie, "https://www.facebook.com");
2643
+ ctx.jar.setCookie(cookie2, "https://www.messenger.com");
2644
+ }
2645
+
2646
+ // On every request we check if we got a DTSG and we mutate the context so that we use the latest
2647
+ // one for the next requests.
2648
+ if (res.jsmods && Array.isArray(res.jsmods.require)) {
2649
+ var arr = res.jsmods.require;
2650
+ for (var i in arr) {
2651
+ if (arr[i][0] === "DTSG" && arr[i][1] === "setToken") {
2652
+ ctx.fb_dtsg = arr[i][3][0];
2653
+
2654
+ // Update ttstamp since that depends on fb_dtsg
2655
+ ctx.ttstamp = "2";
2656
+ for (var j = 0; j < ctx.fb_dtsg.length; j++) ctx.ttstamp += ctx.fb_dtsg.charCodeAt(j);
2657
+ }
2658
+ }
2659
+ }
2660
+
2661
+ if (res.error === 1357001) {
2662
+ if (global.Fca.Require.FastConfig.AutoLogin && global.Fca.Require.FastConfig.CheckPointBypass['956'].Allow) {
2663
+ return global.Fca.Require.logger.Warning(global.Fca.Require.Language.Index.Bypass_956, async function() {
2664
+ const Check = () => new Promise((re) => {
2665
+ defaultFuncs.get('https://facebook.com', ctx.jar).then(function(res) {
2666
+ if (res.headers.location && res.headers.location.includes('https://www.facebook.com/checkpoint/')) {
2667
+ if (res.headers.includes('828281030927956')) return global.Fca.Action('Bypass', ctx, "956", defaultFuncs)
2668
+ else return global.Fca.Require.logger.Error(global.Fca.Require.Language.Index.ErrAppState);
2669
+ }
2670
+ else return global.Fca.Require.logger.Warning(global.Fca.Require.Language.Index.AutoLogin, function() {
2671
+ return global.Fca.Action('AutoLogin');
2672
+ });
2673
+ })
2674
+ })
2675
+ await Check();
2676
+ });
2677
+ }
2678
+ if (global.Fca.Require.FastConfig.AutoLogin) {
2679
+ return global.Fca.Require.logger.Warning(global.Fca.Require.Language.Index.AutoLogin, function() {
2680
+ return global.Fca.Action('AutoLogin');
2681
+ });
2682
+ }
2683
+ else if (!global.Fca.Require.FastConfig.AutoLogin) {
2684
+ return global.Fca.Require.logger.Error(global.Fca.Require.Language.Index.ErrAppState);
2685
+ }
2686
+ return;
2687
+ }
2688
+ else return res;
2689
+ });
2690
+ };
2691
+ }
2692
+
2693
+ /**
2694
+ * @param {{ setCookie: (arg0: any, arg1: string) => void; }} jar
2695
+ */
2696
+
2697
+ function saveCookies(jar) {
2698
+ return function(/** @type {{ headers: { [x: string]: any[]; }; }} */res) {
2699
+ var cookies = res.headers["set-cookie"] || [];
2700
+ cookies.forEach(function(/** @type {string} */c) {
2701
+ if (c.indexOf(".facebook.com") > -1) { // yo wtf is this?
2702
+ jar.setCookie(c, "https://www.facebook.com");
2703
+ jar.setCookie(c.replace(/domain=\.facebook\.com/, "domain=.messenger.com"), "https://www.messenger.com");
2704
+ }
2705
+ });
2706
+ return res;
2707
+ };
2708
+ }
2709
+
2710
+ var NUM_TO_MONTH = [
2711
+ "Jan",
2712
+ "Feb",
2713
+ "Mar",
2714
+ "Apr",
2715
+ "May",
2716
+ "Jun",
2717
+ "Jul",
2718
+ "Aug",
2719
+ "Sep",
2720
+ "Oct",
2721
+ "Nov",
2722
+ "Dec"
2723
+ ];
2724
+ var NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
2725
+
2726
+ /**
2727
+ * @param {{ getUTCDate: () => any; getUTCHours: () => any; getUTCMinutes: () => any; getUTCSeconds: () => any; getUTCDay: () => string | number; getUTCMonth: () => string | number; getUTCFullYear: () => string; }} date
2728
+ */
2729
+
2730
+ function formatDate(date) {
2731
+ var d = date.getUTCDate();
2732
+ d = d >= 10 ? d : "0" + d;
2733
+ var h = date.getUTCHours();
2734
+ h = h >= 10 ? h : "0" + h;
2735
+ var m = date.getUTCMinutes();
2736
+ m = m >= 10 ? m : "0" + m;
2737
+ var s = date.getUTCSeconds();
2738
+ s = s >= 10 ? s : "0" + s;
2739
+ return (NUM_TO_DAY[date.getUTCDay()] + ", " + d + " " + NUM_TO_MONTH[date.getUTCMonth()] + " " + date.getUTCFullYear() + " " + h + ":" + m + ":" + s + " GMT");
2740
+ }
2741
+
2742
+ /**
2743
+ * @param {string[]} arr
2744
+ * @param {string} url
2745
+ */
2746
+
2747
+ function formatCookie(arr, url) {
2748
+ return arr[0] + "=" + arr[1] + "; Path=" + arr[3] + "; Domain=" + url + ".com";
2749
+ }
2750
+
2751
+ /**
2752
+ * @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
2753
+ */
2754
+
2755
+ function formatThread(data) {
2756
+ return {
2757
+ threadID: formatID(data.thread_fbid.toString()),
2758
+ participants: data.participants.map(formatID),
2759
+ participantIDs: data.participants.map(formatID),
2760
+ name: data.name,
2761
+ nicknames: data.custom_nickname,
2762
+ snippet: data.snippet,
2763
+ snippetAttachments: data.snippet_attachments,
2764
+ snippetSender: formatID((data.snippet_sender || "").toString()),
2765
+ unreadCount: data.unread_count,
2766
+ messageCount: data.message_count,
2767
+ imageSrc: data.image_src,
2768
+ timestamp: data.timestamp,
2769
+ muteUntil: data.mute_until,
2770
+ isCanonicalUser: data.is_canonical_user,
2771
+ isCanonical: data.is_canonical,
2772
+ isSubscribed: data.is_subscribed,
2773
+ folder: data.folder,
2774
+ isArchived: data.is_archived,
2775
+ recipientsLoadable: data.recipients_loadable,
2776
+ hasEmailParticipant: data.has_email_participant,
2777
+ readOnly: data.read_only,
2778
+ canReply: data.can_reply,
2779
+ cannotReplyReason: data.cannot_reply_reason,
2780
+ lastMessageTimestamp: data.last_message_timestamp,
2781
+ lastReadTimestamp: data.last_read_timestamp,
2782
+ lastMessageType: data.last_message_type,
2783
+ emoji: data.custom_like_icon,
2784
+ color: data.custom_color,
2785
+ adminIDs: data.admin_ids,
2786
+ threadType: data.thread_type
2787
+ };
2788
+ }
2789
+
2790
+ /**
2791
+ * @param {any} obj
2792
+ */
2793
+
2794
+ function getType(obj) {
2795
+ return Object.prototype.toString.call(obj).slice(8, -1);
2796
+ }
2797
+
2798
+ /**
2799
+ * @param {{ lat: number; p: any; }} presence
2800
+ * @param {any} userID
2801
+ */
2802
+
2803
+ function formatProxyPresence(presence, userID) {
2804
+ if (presence.lat === undefined || presence.p === undefined) return null;
2805
+ return {
2806
+ type: "presence",
2807
+ timestamp: presence.lat * 1000,
2808
+ userID: userID || '',
2809
+ statuses: presence.p
2810
+ };
2811
+ }
2812
+
2813
+ /**
2814
+ * @param {{ la: number; a: any; }} presence
2815
+ * @param {any} userID
2816
+ */
2817
+
2818
+ function formatPresence(presence, userID) {
2819
+ return {
2820
+ type: "presence",
2821
+ timestamp: presence.la * 1000,
2822
+ userID: userID || '',
2823
+ statuses: presence.a
2824
+ };
2825
+ }
2826
+
2827
+ /**
2828
+ * @param {any} payload
2829
+ */
2830
+
2831
+ function decodeClientPayload(payload) {
2832
+ /*
2833
+ Special function which Client using to "encode" clients JSON payload
2834
+ */
2835
+
2836
+ /**
2837
+ * @param {string | any[]} array
2838
+ */
2839
+
2840
+ function Utf8ArrayToStr(array) {
2841
+ var out, i, len, c;
2842
+ var char2, char3;
2843
+ out = "";
2844
+ len = array.length;
2845
+ i = 0;
2846
+ while (i < len) {
2847
+ c = array[i++];
2848
+ switch (c >> 4) {
2849
+ case 0:
2850
+ case 1:
2851
+ case 2:
2852
+ case 3:
2853
+ case 4:
2854
+ case 5:
2855
+ case 6:
2856
+ case 7:
2857
+ out += String.fromCharCode(c);
2858
+ break;
2859
+ case 12:
2860
+ case 13:
2861
+ char2 = array[i++];
2862
+ out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
2863
+ break;
2864
+ case 14:
2865
+ char2 = array[i++];
2866
+ char3 = array[i++];
2867
+ out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
2868
+ break;
2869
+ }
2870
+ }
2871
+ return out;
2872
+ }
2873
+ return JSON.parse(Utf8ArrayToStr(payload));
2874
+ }
2875
+
2876
+ /**
2877
+ * @param {{ getCookies: (arg0: string) => string | any[]; }} jar
2878
+ */
2879
+
2880
+ function getAppState(jar, Encode) {
2881
+ var prettyMilliseconds = require('pretty-ms');
2882
+ var getText = globalThis.Fca.getText;
2883
+ var Security = require("./Extra/Security/Base");
2884
+ var appstate = jar.getCookies("https://www.facebook.com").concat(jar.getCookies("https://facebook.com")).concat(jar.getCookies("https://www.messenger.com"));
2885
+ var logger = require('./logger'),languageFile = require('./Language/index.json');
2886
+ var Language = languageFile.find(i => i.Language == globalThis.Fca.Require.FastConfig.Language).Folder.Index;
2887
+ var data;
2888
+ switch (require(process.cwd() + "/FastConfigFca.json").EncryptFeature) {
2889
+ case true: {
2890
+ if (Encode == undefined) Encode = true;
2891
+ if (process.env['FBKEY'] != undefined && Encode) {
2892
+ logger.Normal(Language.EncryptSuccess);
2893
+ data = Security(JSON.stringify(appstate),process.env['FBKEY'],"Encrypt");
2894
+ }
2895
+ else return appstate;
2896
+ }
2897
+ break;
2898
+ case false: {
2899
+ data = appstate;
2900
+ }
2901
+ break;
2902
+ default: {
2903
+ logger.Normal(getText(Language.IsNotABoolean,require(process.cwd() + "/FastConfigFca.json").EncryptFeature));
2904
+ data = appstate;
2905
+ }
2906
+ }
2907
+ if(!globalThis.Fca.Setting.get('getAppState')) {
2908
+ logger.Normal(getText(Language.ProcessDone,`${prettyMilliseconds(Date.now() - globalThis.Fca.startTime)}`),function() { globalThis.Fca.Setting.set('getAppState',true); });
2909
+ }
2910
+ return data;
2911
+ }
2912
+
2913
+ function getData_Path(Obj , Arr, Stt) {
2914
+ //default stt = 0
2915
+ if (Arr.length === 0 && Obj != undefined) {
2916
+ return Obj; //object
2917
+ }
2918
+ else if (Obj == undefined) {
2919
+ return Stt;
2920
+ }
2921
+ const head = Arr[0];
2922
+ if (head == undefined) {
2923
+ return Stt;
2924
+ }
2925
+ const tail = Arr.slice(1);
2926
+ return getData_Path(Obj[head], tail, Stt++);
2927
+ }
2928
+
2929
+
2930
+ function setData_Path(obj, path, value) {
2931
+ if (!path.length) {
2932
+ return obj;
2933
+ }
2934
+ const currentKey = path[0];
2935
+ let currentObj = obj[currentKey];
2936
+
2937
+ if (!currentObj) {
2938
+ obj[currentKey] = value;
2939
+ currentObj = obj[currentKey];
2940
+ }
2941
+ path.shift();
2942
+ if (!path.length) {
2943
+ currentObj = value;
2944
+ } else {
2945
+ currentObj = setData_Path(currentObj, path, value);
2946
+ }
2947
+
2948
+ return obj;
2949
+ }
2950
+
2951
+ function getPaths(obj, parentPath = []) {
2952
+ let paths = [];
2953
+ for (let prop in obj) {
2954
+ if (typeof obj[prop] === "object") {
2955
+ paths = paths.concat(getPaths(obj[prop], [...parentPath, prop]));
2956
+ } else {
2957
+ paths.push([...parentPath, prop]);
2958
+ }
2959
+ }
2960
+ return paths;
2961
+ }
2962
+
2963
+ function cleanHTML (text) {
2964
+ text = text.replace(/(<br>)|(<\/?i>)|(<\/?em>)|(<\/?b>)|(!?~)|(&amp;)|(&#039;)|(&lt;)|(&gt;)|(&quot;)/g, (match) => {
2965
+ switch (match) {
2966
+ case "<br>":
2967
+ return "\n";
2968
+ case "<i>":
2969
+ case "<em>":
2970
+ case "</i>":
2971
+ case "</em>":
2972
+ return "*";
2973
+ case "<b>":
2974
+ case "</b>":
2975
+ return "**";
2976
+ case "~!":
2977
+ case "!~":
2978
+ return "||";
2979
+ case "&amp;":
2980
+ return "&";
2981
+ case "&#039;":
2982
+ return "'";
2983
+ case "&lt;":
2984
+ return "<";
2985
+ case "&gt;":
2986
+ return ">";
2987
+ case "&quot;":
2988
+ return '"';
2989
+ }
2990
+ });
2991
+ return text;
2992
+ }
2993
+
2994
+ module.exports = {
2995
+ cleanHTML,
2996
+ isReadableStream:isReadableStream,
2997
+ get:get,
2998
+ post:post,
2999
+ postFormData:postFormData,
3000
+ generateThreadingID:generateThreadingID,
3001
+ generateOfflineThreadingID:generateOfflineThreadingID,
3002
+ getGUID:getGUID,
3003
+ getFrom:getFrom,
3004
+ makeParsable:makeParsable,
3005
+ arrToForm:arrToForm,
3006
+ getSignatureID:getSignatureID,
3007
+ getJar: request.jar,
3008
+ generateTimestampRelative:generateTimestampRelative,
3009
+ makeDefaults:makeDefaults,
3010
+ parseAndCheckLogin:parseAndCheckLogin,
3011
+ getGender: getGenderByPhysicalMethod,
3012
+ getData_Path,
3013
+ setData_Path,
3014
+ getPaths,
3015
+ saveCookies,
3016
+ getType,
3017
+ _formatAttachment,
3018
+ formatHistoryMessage,
3019
+ formatID,
3020
+ formatMessage,
3021
+ formatDeltaEvent,
3022
+ formatDeltaMessage,
3023
+ formatProxyPresence,
3024
+ formatPresence,
3025
+ formatTyp,
3026
+ formatDeltaReadReceipt,
3027
+ formatCookie,
3028
+ formatThread,
3029
+ formatReadReceipt,
3030
+ formatRead,
3031
+ generatePresence,
3032
+ generateAccessiblityCookie,
3033
+ formatDate,
3034
+ decodeClientPayload,
3035
+ getAppState,
3036
+ getAdminTextMessageType,
3037
+ setProxy
3038
+ };