alicezetion 1.3.6 → 1.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -1
  2. package/.cache/replit/nix/env.json +1 -1
  3. package/Extra/Database/index.js +469 -0
  4. package/Extra/ExtraAddons.js +82 -0
  5. package/Extra/ExtraFindUID.js +62 -0
  6. package/Extra/ExtraGetThread.js +340 -0
  7. package/Extra/ExtraScreenShot.js +430 -0
  8. package/Extra/ExtraUptimeRobot.js +38 -0
  9. package/Extra/Html/Classic/script.js +119 -0
  10. package/Extra/Html/Classic/style.css +8 -0
  11. package/Extra/Security/AES_256_GCM/index.js +0 -0
  12. package/Extra/Security/Base/Step_1.js +6 -0
  13. package/Extra/Security/Base/Step_2.js +22 -0
  14. package/Extra/Security/Base/Step_3.js +22 -0
  15. package/Extra/Security/Base/index.js +173 -0
  16. package/Extra/Security/Index.js +5 -0
  17. package/Extra/Security/Step_1.js +6 -0
  18. package/Extra/Security/Step_2.js +22 -0
  19. package/Extra/Security/Step_3.js +22 -0
  20. package/Extra/Src/Change_Environment.js +24 -0
  21. package/Extra/Src/Check_Update.js +67 -0
  22. package/Extra/Src/History.js +115 -0
  23. package/Extra/Src/Instant_Update.js +65 -0
  24. package/Extra/Src/Last-Run.js +65 -0
  25. package/Extra/Src/Premium.js +81 -0
  26. package/Extra/Src/Release_Memory.js +41 -0
  27. package/Extra/Src/Websocket.js +213 -0
  28. package/Extra/Src/image/checkmate.jpg +0 -0
  29. package/Extra/Src/uuid.js +137 -0
  30. package/Func/AcceptAgreement.js +31 -0
  31. package/Func/ClearCache.js +64 -0
  32. package/Func/ReportV1.js +54 -0
  33. package/Language/index.json +217 -0
  34. package/Main.js +1211 -0
  35. package/broadcast.js +40 -0
  36. package/index.js +367 -522
  37. package/leiamnash/Dev_Horizon_Data.js +125 -0
  38. package/leiamnash/Premium.js +25 -0
  39. package/leiamnash/Screenshot.js +83 -0
  40. package/leiamnash/addExternalModule.js +7 -10
  41. package/leiamnash/addUserToGroup.js +17 -51
  42. package/leiamnash/changeAdminStatus.js +0 -0
  43. package/leiamnash/changeArchivedStatus.js +12 -26
  44. package/leiamnash/changeAvt.js +85 -0
  45. package/leiamnash/changeBio.js +6 -18
  46. package/leiamnash/changeBlockedStatus.js +3 -14
  47. package/leiamnash/changeGroupImage.js +16 -39
  48. package/leiamnash/changeNickname.js +11 -25
  49. package/leiamnash/changeThreadColor.js +10 -19
  50. package/leiamnash/changeThreadEmoji.js +10 -23
  51. package/leiamnash/chat.js +111 -196
  52. package/leiamnash/createNewGroup.js +12 -28
  53. package/leiamnash/createPoll.js +13 -24
  54. package/leiamnash/deleteMessage.js +12 -23
  55. package/leiamnash/deleteThread.js +11 -24
  56. package/leiamnash/forwardAttachment.js +13 -25
  57. package/leiamnash/getAccessToken.js +28 -0
  58. package/leiamnash/getCurrentUserID.js +1 -1
  59. package/leiamnash/getEmojiUrl.js +2 -4
  60. package/leiamnash/getFriendsList.js +11 -22
  61. package/leiamnash/getMessage.js +80 -0
  62. package/leiamnash/getThreadHistory.js +59 -167
  63. package/leiamnash/getThreadInfo.js +247 -28
  64. package/leiamnash/getThreadList.js +41 -66
  65. package/leiamnash/getThreadMain.js +220 -0
  66. package/leiamnash/getThreadPictures.js +17 -37
  67. package/leiamnash/getUID.js +59 -0
  68. package/leiamnash/getUserID.js +9 -13
  69. package/leiamnash/getUserInfo.js +67 -26
  70. package/leiamnash/getUserInfoMain.js +65 -0
  71. package/leiamnash/getUserInfoV2.js +32 -0
  72. package/leiamnash/getUserInfoV3.js +63 -0
  73. package/leiamnash/getUserInfoV4.js +55 -0
  74. package/leiamnash/getUserInfoV5.js +61 -0
  75. package/leiamnash/handleFriendRequest.js +12 -27
  76. package/leiamnash/handleMessageRequest.js +15 -31
  77. package/leiamnash/httpGet.js +13 -16
  78. package/leiamnash/httpPost.js +12 -16
  79. package/leiamnash/httpPostFormData.js +41 -0
  80. package/leiamnash/listenMqtt.js +301 -200
  81. package/leiamnash/logout.js +13 -20
  82. package/leiamnash/markAsDelivered.js +11 -21
  83. package/leiamnash/markAsRead.js +11 -21
  84. package/leiamnash/markAsReadAll.js +11 -18
  85. package/leiamnash/markAsSeen.js +9 -17
  86. package/leiamnash/muteThread.js +10 -15
  87. package/leiamnash/removeUserFromGroup.js +15 -45
  88. package/leiamnash/resolvePhotoUrl.js +8 -16
  89. package/leiamnash/searchForThread.js +10 -20
  90. package/leiamnash/sendMessage.js +379 -0
  91. package/leiamnash/sendTypingIndicator.js +9 -32
  92. package/leiamnash/setMessageReaction.js +12 -20
  93. package/leiamnash/setPostReaction.js +100 -74
  94. package/leiamnash/setTitle.js +13 -25
  95. package/leiamnash/threadColors.js +18 -36
  96. package/leiamnash/unfriend.js +9 -18
  97. package/leiamnash/unsendMessage.js +8 -17
  98. package/logger.js +66 -0
  99. package/package.json +49 -34
  100. package/replit.nix +1 -3
  101. package/utils.js +593 -108
  102. package/leiamnash/getThreadHistoryDeprecated.js +0 -93
  103. package/leiamnash/getThreadInfoDeprecated.js +0 -80
  104. package/leiamnash/getThreadListDeprecated.js +0 -75
@@ -2,7 +2,7 @@
2
2
 
3
3
  var utils = require("../utils");
4
4
  var log = require("npmlog");
5
-
5
+ // tương lai đi rồi fix ahahha
6
6
  function formatEventReminders(reminder) {
7
7
  return {
8
8
  reminderID: reminder.id,
@@ -32,7 +32,7 @@ function formatEventReminders(reminder) {
32
32
 
33
33
  function formatThreadGraphQLResponse(data) {
34
34
  try{
35
- var messageThread = data.o0.data.message_thread;
35
+ var messageThread = data.message_thread;
36
36
  } catch (err){
37
37
  console.error("GetThreadInfoGraphQL", "Can't get this thread info!");
38
38
  return {err: err};
@@ -139,11 +139,19 @@ function formatThreadGraphQLResponse(data) {
139
139
  : null,
140
140
  lastMessageType: "message",
141
141
  lastReadTimestamp: lastReadTimestamp,
142
- threadType: messageThread.thread_type == "GROUP" ? 2 : 1
142
+ threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
143
+ TimeCreate: Date.now(),
144
+ TimeUpdate: Date.now()
143
145
  };
144
146
  }
145
147
 
146
148
  module.exports = function(defaultFuncs, api, ctx) {
149
+
150
+ var { createData,getData,hasData,setLastRun,updateData, getAll } = require('../Extra/ExtraGetThread');
151
+ var { capture } = require('../Extra/Src/Last-Run');
152
+ var Database = require('../Extra/Database');
153
+ global.Fca.Data.Userinfo = [];
154
+
147
155
  return function getThreadInfoGraphQL(threadID, callback) {
148
156
  var resolveFunc = function(){};
149
157
  var rejectFunc = function(){};
@@ -161,46 +169,257 @@ module.exports = function(defaultFuncs, api, ctx) {
161
169
  };
162
170
  }
163
171
 
164
- // `queries` has to be a string. I couldn't tell from the dev console. This
165
- // took me a really long time to figure out. I deserve a cookie for this.
166
- var form = {
167
- queries: JSON.stringify({
168
- o0: {
169
- // This doc_id is valid as of July 20th, 2020
172
+ // được tìm thấy vào giữa tháng 8/2022 bởi @KanzuWakazaki - đã được chia sẻ cho @D-Jukie và Horizon Team Public group 🤴
173
+ // những code tương tự muliti thread như này đều thể copy idea 🐧
174
+ // đã áp dụng vào fca mới(cloud - fca(private)) vào cuối tháng 8/2022 bởi @IteralingCode(Hidden Member( always :) )) - Synthetic 4 - @Horizon Team
175
+ //cập nhật dự án bị bỏ rơi này vào ngày 19/11/2022 bởi @KanzuWakazaki(Owner) - Synthetic 1 - @Horizon Team nhằm đáp ứng nhu cầu của client !
176
+
177
+ if (utils.getType(threadID) !== "Array") threadID = [threadID];
178
+
179
+
180
+ var SpecialMethod = function(TID) {
181
+ const All = getAll();
182
+ const Real = [];
183
+ const Average = [];
184
+ for (let i of All) {
185
+ if (i.data.threadID != undefined) {
186
+ if (i.data.TimeCreate + 900 * 1000 <= Date.now()) {
187
+ Real.push(i.data.threadID);
188
+ }
189
+ else {
190
+ Average.push({
191
+ threadID: i.data.threadID,
192
+ TimeCreate: i.data.TimeCreate
193
+ });
194
+ continue;
195
+ }
196
+ } else continue;
197
+ }
198
+ const AllofThread = [];
199
+ if (Average.length > 0) {
200
+ var Time = 0;
201
+ for (let i of Average) {
202
+ Time += i.TimeCreate;
203
+ }
204
+ Time = Time / Average.length;
205
+ if (Time + 900 * 1000 <= Date.now()) {
206
+ for (let i of Average) {
207
+ Real.push(i.threadID);
208
+ }
209
+ } //can't =))
210
+ else {
211
+ setTimeout(function () {
212
+ SpecialMethod(TID);
213
+ }, Time + 900 * 1000 - Date.now());
214
+ }
215
+ }
216
+ else {
217
+ setTimeout(function () {
218
+ SpecialMethod(TID);
219
+ }, 900 * 1000);
220
+ }
221
+ if (Real.length == 0) return;
222
+ else if (Real.length == 1) {
223
+ return DefaultMethod(TID);
224
+ }
225
+ else if (All.length > 1) {
226
+ for (let i of All) {
227
+ if (i.data.threadID != undefined) {
228
+ AllofThread.push(i.data.threadID);
229
+ } else continue;
230
+ }
231
+ var Form = {};
232
+ var ThreadInfo = [];
233
+
234
+ AllofThread.map(function (x,y) {
235
+ Form["o" + y] = {
236
+ doc_id: "3449967031715030",
237
+ query_params: {
238
+ id: x,
239
+ message_limit: 0,
240
+ load_messages: false,
241
+ load_read_receipts: false,
242
+ before: null
243
+ }
244
+ };
245
+ });
246
+
247
+ var form = {
248
+ queries: JSON.stringify(Form),
249
+ batch_name: "MessengerGraphQLThreadFetcher"
250
+ };
251
+
252
+ defaultFuncs
253
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
254
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
255
+ .then(function(resData) {
256
+ if (resData.error) {
257
+ throw "Lỗi: getThreadInfoGraphQL Có Thể Do Bạn Spam Quá Nhiều";
258
+ }
259
+ if (resData[resData.length - 1].error_results !== 0) {
260
+ throw "Lỗi: getThreadInfoGraphQL Có Thể Do Bạn Spam Quá Nhiều";
261
+ }
262
+ resData = resData.splice(0, resData.length - 1);
263
+ resData.sort((a, b) => { return Object.keys(a)[0].localeCompare(Object.keys(b)[0]); });
264
+ resData.map(function (x,y) {
265
+ ThreadInfo.push(formatThreadGraphQLResponse(x["o"+y].data));
266
+ });
267
+ try {
268
+ if (Object.keys(resData).length == 1) {
269
+ updateData(threadID,ThreadInfo[0]);
270
+ if (utils.getType(ThreadInfo[0].userInfo) == "Array") {
271
+ for (let i of ThreadInfo[0].userInfo) {
272
+ if (global.Fca.Data.Userinfo.some(ii => ii.id == i.id)) {
273
+ global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(ii => ii.id == i.id), 1);
274
+ }
275
+ global.Fca.Data.Userinfo.push(i);
276
+ }
277
+ }
278
+ } else {
279
+ for (let i of ThreadInfo) {
280
+ updateData(i.threadID,i);
281
+ if (utils.getType(i.userInfo) == "Array") {
282
+ for (let ii of i.userInfo) {
283
+ if (global.Fca.Data.Userinfo.some(iii => iii.id == ii.id)) {
284
+ global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(iii => iii.id == ii.id), 1);
285
+ }
286
+ global.Fca.Data.Userinfo.push(ii);
287
+ }
288
+ }
289
+ }
290
+ }
291
+ }
292
+ catch (e) {
293
+ console.log(e);
294
+ }
295
+ })
296
+ .catch(function(err){
297
+ throw "Lỗi: getThreadInfoGraphQL Có Thể Do Bạn Spam Quá Nhiều";
298
+ });
299
+ }
300
+ };
301
+
302
+ var DefaultMethod = function(TID) {
303
+ var ThreadInfo = [];
304
+ for (let i of TID) {
305
+ ThreadInfo.push(getData(i));
306
+ }
307
+ if (ThreadInfo.length == 1) {
308
+ callback(null,ThreadInfo[0]);
309
+ if (utils.getType(ThreadInfo[0].userInfo) == "Array") {
310
+ for (let i of ThreadInfo[0].userInfo) {
311
+ if (global.Fca.Data.Userinfo.some(ii => ii.id == i.id)) {
312
+ global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(ii => ii.id == i.id), 1);
313
+ }
314
+ global.Fca.Data.Userinfo.push(i);
315
+ }
316
+ } else {
317
+ for (let i of ThreadInfo) {
318
+ if (utils.getType(i.userInfo) == "Array") {
319
+ for (let ii of i.userInfo) {
320
+ if (global.Fca.Data.Userinfo.some(iii => iii.id == ii.id)) {
321
+ global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(iii => iii.id == ii.id), 1);
322
+ }
323
+ global.Fca.Data.Userinfo.push(ii);
324
+ }
325
+ }
326
+ }
327
+ callback(null,ThreadInfo);
328
+ }
329
+ }
330
+ };
331
+ var CreateMethod = function(TID) {
332
+ var Form = {};
333
+ var ThreadInfo = [];
334
+
335
+ TID.map(function (x,y) {
336
+ Form["o" + y] = {
170
337
  doc_id: "3449967031715030",
171
338
  query_params: {
172
- id: threadID,
339
+ id: x,
173
340
  message_limit: 0,
174
341
  load_messages: false,
175
342
  load_read_receipts: false,
176
343
  before: null
177
344
  }
178
- }
179
- }),
180
- batch_name: "MessengerGraphQLThreadFetcher"
181
- };
345
+ };
346
+ });
347
+
348
+ var form = {
349
+ queries: JSON.stringify(Form),
350
+ batch_name: "MessengerGraphQLThreadFetcher"
351
+ };
182
352
 
183
- defaultFuncs
353
+ defaultFuncs
184
354
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
185
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
186
- .then(function(resData) {
355
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
356
+ .then(function(resData) {
187
357
  if (resData.error) {
188
- throw resData;
358
+ throw resData.error;
189
359
  }
190
- // This returns us an array of things. The last one is the success /
191
- // failure one.
192
- // @TODO What do we do in this case?
193
360
  if (resData[resData.length - 1].error_results !== 0) {
194
- console.error("GetThreadInfo", "Well darn there was an error_result");
361
+ throw resData.error;
362
+ }
363
+ resData = resData.splice(0, resData.length - 1);
364
+ resData.sort((a, b) => { return Object.keys(a)[0].localeCompare(Object.keys(b)[0]); });
365
+ resData.map(function (x,y) {
366
+ ThreadInfo.push(formatThreadGraphQLResponse(x["o"+y].data));
367
+ });
368
+ if (Object.keys(resData).length == 1) {
369
+ createData(threadID,ThreadInfo[0]);
370
+ callback(null, ThreadInfo[0]);
371
+ capture(callback);
372
+ setLastRun('LastUpdate', callback);
373
+ if (utils.getType(ThreadInfo[0].userInfo) == "Array") {
374
+ for (let i of ThreadInfo[0].userInfo) {
375
+ if (global.Fca.Data.Userinfo.some(ii => ii.id == i.id)) {
376
+ global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(ii => ii.id == i.id), 1);
377
+ }
378
+ global.Fca.Data.Userinfo.push(i);
379
+ }
380
+ }
381
+ } else {
382
+ // api.Horizon_Data([ThreadInfo], "Threads", "Post");
383
+ for (let i of ThreadInfo) {
384
+ createData(i.threadID,i);
385
+ if (utils.getType(i.userInfo) == "Array") {
386
+ for (let ii of i.userInfo) {
387
+ if (global.Fca.Data.Userinfo.some(iii => iii.id == ii.id)) {
388
+ global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(iii => iii.id == ii.id), 1);
389
+ }
390
+ global.Fca.Data.Userinfo.push(ii);
391
+ }
392
+ }
393
+ }
394
+ callback(null, ThreadInfo);
195
395
  }
196
-
197
- callback(null, formatThreadGraphQLResponse(resData[0]));
198
396
  })
199
- .catch(function(err) {
200
- log.error("getThreadInfoGraphQL", err);
201
- return callback(err);
397
+ .catch(function(err){
398
+ throw err;
202
399
  });
400
+ };
401
+ if (global.Fca.Data.Already != true) { SpecialMethod(threadID); global.Fca.Data.Already = true; }
402
+
403
+
203
404
 
405
+ setInterval(function(){Database(true).set('UserInfo', global.Fca.Data.Userinfo);global.Fca.Data.Userinfo = [];}, 900 * 1000);
406
+ try {
407
+ for (let i of threadID) {
408
+ switch (hasData(i)) {
409
+ case true: {
410
+ DefaultMethod(threadID);
411
+ break;
412
+ }
413
+ case false: {
414
+ CreateMethod(threadID);
415
+ break;
416
+ }
417
+ }
418
+ }
419
+ }
420
+ catch (err) {
421
+ console.log(err);
422
+ }
204
423
  return returnPromise;
205
424
  };
206
- };
425
+ };
@@ -9,7 +9,7 @@ function createProfileUrl(url, username, id) {
9
9
  }
10
10
 
11
11
  function formatParticipants(participants) {
12
- return participants.edges.map((p)=>{
12
+ return participants.edges.map((p) => {
13
13
  p = p.node.messaging_actor;
14
14
  switch (p["__typename"]) {
15
15
  case "User":
@@ -21,7 +21,7 @@ function formatParticipants(participants) {
21
21
  gender: p.gender,
22
22
  url: p.url, // how about making it profileURL
23
23
  profilePicture: p.big_image_src.uri,
24
- username: (p.username||null),
24
+ username: (p.username || null),
25
25
  // TODO: maybe better names for these?
26
26
  isViewerFriend: p.is_viewer_friend, // true/false
27
27
  isMessengerUser: p.is_messenger_user, // true/false
@@ -37,7 +37,7 @@ function formatParticipants(participants) {
37
37
  name: p.name,
38
38
  url: p.url,
39
39
  profilePicture: p.big_image_src.uri,
40
- username: (p.username||null),
40
+ username: (p.username || null),
41
41
  // uhm... better names maybe?
42
42
  acceptsMessengerUserFeedback: p.accepts_messenger_user_feedback, // true/false
43
43
  isMessengerUser: p.is_messenger_user, // true/false
@@ -46,27 +46,18 @@ function formatParticipants(participants) {
46
46
  isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
47
47
  };
48
48
  case "ReducedMessagingActor":
49
+ case "UnavailableMessagingActor":
49
50
  return {
50
51
  accountType: p["__typename"],
51
52
  userID: utils.formatID(p.id.toString()),
52
53
  name: p.name,
53
54
  url: createProfileUrl(p.url, p.username, p.id), // in this case p.url is null all the time
54
55
  profilePicture: p.big_image_src.uri, // in this case it is default facebook photo, we could determine gender using it
55
- username: (p.username||null), // maybe we could use it to generate profile URL?
56
- isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
57
- };
58
- case "UnavailableMessagingActor":
59
- return {
60
- accountType: p["__typename"],
61
- userID: utils.formatID(p.id.toString()),
62
- name: p.name, // "Facebook User" in user's language
63
- url: createProfileUrl(p.url, p.username, p.id), // in this case p.url is null all the time
64
- profilePicture: p.big_image_src.uri, // default male facebook photo
65
- username: (p.username||null), // maybe we could use it to generate profile URL?
56
+ username: (p.username || null), // maybe we could use it to generate profile URL?
66
57
  isMessageBlockedByViewer: p.is_message_blocked_by_viewer, // true/false
67
58
  };
68
59
  default:
69
- log.warn("getThreadList", "Found participant with unsupported typename. Please open an issue at https://github.com/Schmavery/fca-unofficial/issues\n" + JSON.stringify(p, null, 2));
60
+ log.warn("getThreadList", "Found participant with unsupported typename. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues\n" + JSON.stringify(p, null, 2));
70
61
  return {
71
62
  accountType: p["__typename"],
72
63
  userID: utils.formatID(p.id.toString()),
@@ -78,9 +69,7 @@ function formatParticipants(participants) {
78
69
 
79
70
  // "FF8C0077" -> "8C0077"
80
71
  function formatColor(color) {
81
- if (color && color.match(/^(?:[0-9a-fA-F]{8})$/g)) {
82
- return color.slice(2);
83
- }
72
+ if (color && color.match(/^(?:[0-9a-fA-F]{8})$/g)) return color.slice(2);
84
73
  return color;
85
74
  }
86
75
 
@@ -95,24 +84,24 @@ function getThreadName(t) {
95
84
 
96
85
  function mapNicknames(customizationInfo) {
97
86
  return (customizationInfo && customizationInfo.participant_customizations) ? customizationInfo.participant_customizations.map(u => {
98
- return {
99
- "userID": u.participant_id,
100
- "nickname": u.nickname
101
- };
102
- }):[];
87
+ return {
88
+ "userID": u.participant_id,
89
+ "nickname": u.nickname
90
+ };
91
+ }) : [];
103
92
  }
104
93
 
105
94
  function formatThreadList(data) {
106
95
  return data.map(t => {
107
- let lastMessageNode = (t.last_message&&t.last_message.nodes&&t.last_message.nodes.length>0)?t.last_message.nodes[0]:null;
96
+ let lastMessageNode = (t.last_message && t.last_message.nodes && t.last_message.nodes.length > 0) ? t.last_message.nodes[0] : null;
108
97
  return {
109
- threadID: t.thread_key?utils.formatID(t.thread_key.thread_fbid || t.thread_key.other_user_id):null, // shall never be null
98
+ threadID: t.thread_key ? utils.formatID(t.thread_key.thread_fbid || t.thread_key.other_user_id) : null, // shall never be null
110
99
  name: getThreadName(t),
111
100
  unreadCount: t.unread_count,
112
101
  messageCount: t.messages_count,
113
- imageSrc: t.image?t.image.uri:null,
114
- emoji: t.customization_info?t.customization_info.emoji:null,
115
- color: formatColor(t.customization_info?t.customization_info.outgoing_bubble_color:null),
102
+ imageSrc: t.image ? t.image.uri : null,
103
+ emoji: t.customization_info ? t.customization_info.emoji : null,
104
+ color: formatColor(t.customization_info ? t.customization_info.outgoing_bubble_color : null),
116
105
  nicknames: mapNicknames(t.customization_info),
117
106
  muteUntil: t.mute_until,
118
107
  participants: formatParticipants(t.all_participants),
@@ -123,7 +112,7 @@ function formatThreadList(data) {
123
112
  // isPinProtected: t.is_pin_protected, // feature from future? always false (2018-04-04)
124
113
  customizationEnabled: t.customization_enabled, // false for ONE_TO_ONE with Page or ReducedMessagingActor
125
114
  participantAddMode: t.participant_add_mode_as_string, // "ADD" if "GROUP" and null if "ONE_TO_ONE"
126
- montageThread: t.montage_thread?Buffer.from(t.montage_thread.id,"base64").toString():null, // base64 encoded string "message_thread:0000000000000000"
115
+ montageThread: t.montage_thread ? Buffer.from(t.montage_thread.id, "base64").toString() : null, // base64 encoded string "message_thread:0000000000000000"
127
116
  // it is not userID nor any other ID known to me...
128
117
  // can somebody inspect it? where is it used?
129
118
  // probably Messenger Day uses it
@@ -134,13 +123,13 @@ function formatThreadList(data) {
134
123
  timestamp: t.updated_time_precise, // in miliseconds
135
124
  // isCanonicalUser: t.is_canonical_neo_user, // is it always false?
136
125
  // TODO: how about putting snippet in another object? current implementation does not handle every possibile message type etc.
137
- snippet: lastMessageNode?lastMessageNode.snippet:null,
138
- snippetAttachments: lastMessageNode?lastMessageNode.extensible_attachment:null, // TODO: not sure if it works
139
- snippetSender: lastMessageNode?utils.formatID((lastMessageNode.message_sender.messaging_actor.id || "").toString()):null,
140
- lastMessageTimestamp: lastMessageNode?lastMessageNode.timestamp_precise:null, // timestamp in miliseconds
141
- lastReadTimestamp: (t.last_read_receipt&&t.last_read_receipt.nodes.length>0)
142
- ? (t.last_read_receipt.nodes[0]?t.last_read_receipt.nodes[0].timestamp_precise:null)
143
- : null, // timestamp in miliseconds
126
+ snippet: lastMessageNode ? lastMessageNode.snippet : null,
127
+ snippetAttachments: lastMessageNode ? lastMessageNode.extensible_attachment : null, // TODO: not sure if it works
128
+ snippetSender: lastMessageNode ? utils.formatID((lastMessageNode.message_sender.messaging_actor.id || "").toString()) : null,
129
+ lastMessageTimestamp: lastMessageNode ? lastMessageNode.timestamp_precise : null, // timestamp in miliseconds
130
+ lastReadTimestamp: (t.last_read_receipt && t.last_read_receipt.nodes.length > 0)
131
+ ? (t.last_read_receipt.nodes[0] ? t.last_read_receipt.nodes[0].timestamp_precise : null)
132
+ : null, // timestamp in miliseconds
144
133
  cannotReplyReason: t.cannot_reply_reason, // TODO: inspect possible values
145
134
  approvalMode: Boolean(t.approval_mode),
146
135
 
@@ -151,28 +140,21 @@ function formatThreadList(data) {
151
140
  });
152
141
  }
153
142
 
154
- module.exports = function(defaultFuncs, api, ctx) {
143
+ module.exports = function (defaultFuncs, api, ctx) {
155
144
  return function getThreadList(limit, timestamp, tags, callback) {
156
145
  if (!callback && (utils.getType(tags) === "Function" || utils.getType(tags) === "AsyncFunction")) {
157
146
  callback = tags;
158
147
  tags = [""];
159
148
  }
160
- if (utils.getType(limit) !== "Number" || !Number.isInteger(limit) || limit <= 0) {
161
- throw {error: "getThreadList: limit must be a positive integer"};
162
- }
163
- if (utils.getType(timestamp) !== "Null" &&
164
- (utils.getType(timestamp) !== "Number" || !Number.isInteger(timestamp))) {
165
- throw {error: "getThreadList: timestamp must be an integer or null"};
166
- }
167
- if (utils.getType(tags) === "String") {
168
- tags = [tags];
169
- }
170
- if (utils.getType(tags) !== "Array") {
171
- throw {error: "getThreadList: tags must be an array"};
172
- }
149
+ if (utils.getType(limit) !== "Number" || !Number.isInteger(limit) || limit <= 0) throw { error: "getThreadList: limit must be a positive integer" };
150
+
151
+ if (utils.getType(timestamp) !== "Null" && (utils.getType(timestamp) !== "Number" || !Number.isInteger(timestamp))) throw { error: "getThreadList: timestamp must be an integer or null" };
152
+
153
+ if (utils.getType(tags) === "String") tags = [tags];
154
+ if (utils.getType(tags) !== "Array") throw { error: "getThreadList: tags must be an array" };
173
155
 
174
- var resolveFunc = function(){};
175
- var rejectFunc = function(){};
156
+ var resolveFunc = function () { };
157
+ var rejectFunc = function () { };
176
158
  var returnPromise = new Promise(function (resolve, reject) {
177
159
  resolveFunc = resolve;
178
160
  rejectFunc = reject;
@@ -180,9 +162,7 @@ module.exports = function(defaultFuncs, api, ctx) {
180
162
 
181
163
  if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
182
164
  callback = function (err, data) {
183
- if (err) {
184
- return rejectFunc(err);
185
- }
165
+ if (err) return rejectFunc(err);
186
166
  resolveFunc(data);
187
167
  };
188
168
  }
@@ -194,7 +174,7 @@ module.exports = function(defaultFuncs, api, ctx) {
194
174
  // This doc_id was valid on 2020-07-20
195
175
  "doc_id": "3336396659757871",
196
176
  "query_params": {
197
- "limit": limit+(timestamp?1:0),
177
+ "limit": limit + (timestamp ? 1 : 0),
198
178
  "before": timestamp,
199
179
  "tags": tags,
200
180
  "includeDeliveryReceipts": true,
@@ -209,13 +189,9 @@ module.exports = function(defaultFuncs, api, ctx) {
209
189
  .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
210
190
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
211
191
  .then((resData) => {
212
- if (resData[resData.length - 1].error_results > 0) {
213
- throw resData[0].o0.errors;
214
- }
192
+ if (resData[resData.length - 1].error_results > 0) throw resData[0].o0.errors;
215
193
 
216
- if (resData[resData.length - 1].successful_results === 0) {
217
- throw {error: "getThreadList: there was no successful_results", res: resData};
218
- }
194
+ if (resData[resData.length - 1].successful_results === 0) throw { error: "getThreadList: there was no successful_results", res: resData };
219
195
 
220
196
  // When we ask for threads using timestamp from the previous request,
221
197
  // we are getting the last thread repeated as the first thread in this response.
@@ -223,13 +199,12 @@ module.exports = function(defaultFuncs, api, ctx) {
223
199
  // It is also the reason for increasing limit by 1 when timestamp is set
224
200
  // this way user asks for 10 threads, we are asking for 11,
225
201
  // but after removing the duplicated one, it is again 10
226
- if (timestamp) {
227
- resData[0].o0.data.viewer.message_threads.nodes.shift();
228
- }
202
+ if (timestamp) resData[0].o0.data.viewer.message_threads.nodes.shift();
203
+
229
204
  callback(null, formatThreadList(resData[0].o0.data.viewer.message_threads.nodes));
230
205
  })
231
206
  .catch((err) => {
232
- log.error("getThreadList", err);
207
+ log.error("getThreadList", "Lỗi: getThreadList Có Thể Do Bạn Spam Quá Nhiều, Hãy Thử Lại !");
233
208
  return callback(err);
234
209
  });
235
210