fca-priyansh 19.0.0 → 20.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/.gitlab-ci.yml +22 -0
  2. package/CountTime.json +1 -0
  3. package/Extra/Balancer.js +49 -49
  4. package/Extra/BroadcastSystem.js +1 -0
  5. package/Extra/Bypass/956/index.js +233 -233
  6. package/Extra/Bypass/test/aaaa.json +169 -169
  7. package/Extra/Bypass/test/index.js +187 -187
  8. package/Extra/Database/index.js +468 -468
  9. package/Extra/ExtraAddons.js +82 -82
  10. package/Extra/ExtraFindUID.js +61 -61
  11. package/Extra/ExtraGetThread.js +365 -365
  12. package/Extra/ExtraScreenShot.js +430 -430
  13. package/Extra/ExtraUptimeRobot.js +142 -38
  14. package/Extra/Html/Classic/script.js +118 -118
  15. package/Extra/Html/Classic/style.css +7 -7
  16. package/Extra/Security/Base/Step_1.js +5 -5
  17. package/Extra/Security/Base/Step_2.js +22 -22
  18. package/Extra/Security/Base/Step_3.js +22 -22
  19. package/Extra/Security/Base/index.js +190 -190
  20. package/Extra/Security/Index.js +4 -4
  21. package/Extra/Security/Step_1.js +5 -5
  22. package/Extra/Security/Step_2.js +22 -22
  23. package/Extra/Security/Step_3.js +22 -22
  24. package/Extra/Src/Change_Environment.js +24 -24
  25. package/Extra/Src/Check_Update.js +66 -66
  26. package/Extra/Src/History.js +114 -114
  27. package/Extra/Src/Instant_Update.js +64 -64
  28. package/Extra/Src/Last-Run.js +64 -64
  29. package/Extra/Src/Premium.js +81 -81
  30. package/Extra/Src/Websocket.js +212 -212
  31. package/Extra/Src/uuid.js +137 -137
  32. package/Func/AcceptAgreement.js +31 -31
  33. package/Func/ClearCache.js +64 -64
  34. package/Func/ReportV1.js +54 -54
  35. package/LICENSE +21 -21
  36. package/Language/index.json +228 -228
  37. package/Main.js +1 -1290
  38. package/README.md +198 -198
  39. package/broadcast.js +1 -44
  40. package/errorHandler.js +151 -0
  41. package/index.js +1 -448
  42. package/logger.js +69 -66
  43. package/package.json +99 -98
  44. package/src/Dev_Horizon_Data.js +124 -124
  45. package/src/Dev_getThreadInfoOLD.js +421 -421
  46. package/src/Dev_shareTest2.js +68 -68
  47. package/src/Dev_shareTest3.js +71 -71
  48. package/src/Premium.js +24 -24
  49. package/src/Screenshot.js +82 -82
  50. package/src/addExternalModule.js +16 -16
  51. package/src/addUserToGroup.js +79 -79
  52. package/src/changeAdminStatus.js +79 -79
  53. package/src/changeArchivedStatus.js +41 -41
  54. package/src/changeAvt.js +84 -84
  55. package/src/changeBio.js +65 -65
  56. package/src/changeBlockedStatus.js +36 -36
  57. package/src/changeGroupImage.js +106 -106
  58. package/src/changeNickname.js +45 -45
  59. package/src/changeThreadColor.js +62 -62
  60. package/src/changeThreadEmoji.js +42 -42
  61. package/src/changeThreadTheme.js +263 -0
  62. package/src/comment.js +244 -0
  63. package/src/createNewGroup.js +70 -70
  64. package/src/createPoll.js +60 -60
  65. package/src/deleteMessage.js +45 -45
  66. package/src/deleteThread.js +43 -43
  67. package/src/editMessage.js +71 -53
  68. package/src/follow.js +119 -0
  69. package/src/forwardAttachment.js +48 -48
  70. package/src/friend.js +383 -0
  71. package/src/getAccessToken.js +27 -27
  72. package/src/getCurrentUserID.js +7 -7
  73. package/src/getEmojiUrl.js +27 -27
  74. package/src/getFriendsList.js +73 -73
  75. package/src/getMessage.js +102 -102
  76. package/src/getPendingFriendRequests.js +45 -0
  77. package/src/getThreadHistory.js +537 -537
  78. package/src/getThreadInfo.js +424 -423
  79. package/src/getThreadInfoOLD.js +421 -421
  80. package/src/getThreadList.js +213 -213
  81. package/src/getThreadMain.js +219 -219
  82. package/src/getThreadPictures.js +59 -59
  83. package/src/getUID.js +58 -58
  84. package/src/getUserID.js +62 -62
  85. package/src/getUserInfo.js +112 -112
  86. package/src/getUserInfoMain.js +64 -64
  87. package/src/getUserInfoV2.js +31 -31
  88. package/src/getUserInfoV3.js +62 -62
  89. package/src/getUserInfoV4.js +54 -54
  90. package/src/getUserInfoV5.js +60 -60
  91. package/src/handleFriendRequest.js +46 -46
  92. package/src/handleMessageRequest.js +49 -49
  93. package/src/httpGet.js +49 -49
  94. package/src/httpPost.js +48 -48
  95. package/src/httpPostFormData.js +40 -40
  96. package/src/listenMqtt.js +1 -956
  97. package/src/listenMqttV1.js +832 -846
  98. package/src/logout.js +68 -68
  99. package/src/markAsDelivered.js +48 -48
  100. package/src/markAsRead.js +70 -70
  101. package/src/markAsReadAll.js +42 -42
  102. package/src/markAsSeen.js +51 -51
  103. package/src/muteThread.js +47 -47
  104. package/src/notes.js +279 -0
  105. package/src/removeUserFromGroup.js +49 -49
  106. package/src/resolvePhotoUrl.js +37 -37
  107. package/src/searchForThread.js +43 -43
  108. package/src/sendMention.js +325 -0
  109. package/src/sendMessage.js +1 -386
  110. package/src/sendMqttMessage.js +70 -70
  111. package/src/sendTypingIndicator.js +79 -80
  112. package/src/setMessageReaction.js +109 -109
  113. package/src/setPostReaction.js +101 -101
  114. package/src/setTitle.js +74 -74
  115. package/src/share.js +98 -0
  116. package/src/shareContact.js +55 -55
  117. package/src/shareLink.js +58 -58
  118. package/src/stickers.js +525 -0
  119. package/src/story.js +267 -0
  120. package/src/threadColors.js +38 -38
  121. package/src/unfriend.js +43 -43
  122. package/src/unsendMessage.js +47 -47
  123. package/src/unsendMqttMessage.js +65 -65
  124. package/test/data/shareAttach.js +146 -146
  125. package/test/data/test.txt +7 -7
  126. package/test/example-config.json +18 -18
  127. package/test/test-page.js +140 -140
  128. package/test/test.js +385 -385
  129. package/test/testv2.js +2 -2
  130. package/userAgentManager.js +129 -0
  131. package/utils.js +1 -3077
  132. package/.github/workflows/publish.yml +0 -20
  133. package/Extra/Src/Release_Memory.js +0 -160
  134. package/Extra/Src/test.js +0 -28
  135. package/SECURITY.md +0 -17
@@ -1,424 +1,425 @@
1
- /* eslint-disable linebreak-style */
2
- "use strict";
3
-
4
- var utils = require("../utils");
5
- // tương lai đi rồi fix ahahha
6
- function formatEventReminders(reminder) {
7
- return {
8
- reminderID: reminder.id,
9
- eventCreatorID: reminder.lightweight_event_creator.id,
10
- time: reminder.time,
11
- eventType: reminder.lightweight_event_type.toLowerCase(),
12
- locationName: reminder.location_name,
13
- // @TODO verify this
14
- locationCoordinates: reminder.location_coordinates,
15
- locationPage: reminder.location_page,
16
- eventStatus: reminder.lightweight_event_status.toLowerCase(),
17
- note: reminder.note,
18
- repeatMode: reminder.repeat_mode.toLowerCase(),
19
- eventTitle: reminder.event_title,
20
- triggerMessage: reminder.trigger_message,
21
- secondsToNotifyBefore: reminder.seconds_to_notify_before,
22
- allowsRsvp: reminder.allows_rsvp,
23
- relatedEvent: reminder.related_event,
24
- members: reminder.event_reminder_members.edges.map(function(member) {
25
- return {
26
- memberID: member.node.id,
27
- state: member.guest_list_state.toLowerCase()
28
- };
29
- })
30
- };
31
- }
32
-
33
- function formatThreadGraphQLResponse(data) {
34
- try{
35
- var messageThread = data.message_thread;
36
- } catch (err){
37
- console.error("GetThreadInfoGraphQL", "Can't get this thread info!");
38
- return {err: err};
39
- }
40
- var threadID = messageThread.thread_key.thread_fbid
41
- ? messageThread.thread_key.thread_fbid
42
- : messageThread.thread_key.other_user_id;
43
-
44
- // Remove me
45
- var lastM = messageThread.last_message;
46
- var snippetID =
47
- lastM &&
48
- lastM.nodes &&
49
- lastM.nodes[0] &&
50
- lastM.nodes[0].message_sender &&
51
- lastM.nodes[0].message_sender.messaging_actor
52
- ? lastM.nodes[0].message_sender.messaging_actor.id
53
- : null;
54
- var snippetText =
55
- lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
56
- var lastR = messageThread.last_read_receipt;
57
- var lastReadTimestamp =
58
- lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
59
- ? lastR.nodes[0].timestamp_precise
60
- : null;
61
-
62
- return {
63
- threadID: threadID,
64
- threadName: messageThread.name,
65
- participantIDs: messageThread.all_participants.edges.map(d => d.node.messaging_actor.id),
66
- userInfo: messageThread.all_participants.edges.map(d => ({
67
- id: d.node.messaging_actor.id,
68
- name: d.node.messaging_actor.name,
69
- firstName: d.node.messaging_actor.short_name,
70
- vanity: d.node.messaging_actor.username,
71
- thumbSrc: d.node.messaging_actor.big_image_src.uri,
72
- profileUrl: d.node.messaging_actor.big_image_src.uri,
73
- gender: d.node.messaging_actor.gender,
74
- type: d.node.messaging_actor.__typename,
75
- isFriend: d.node.messaging_actor.is_viewer_friend,
76
- isBirthday: !!d.node.messaging_actor.is_birthday //not sure?
77
- })),
78
- unreadCount: messageThread.unread_count,
79
- messageCount: messageThread.messages_count,
80
- timestamp: messageThread.updated_time_precise,
81
- muteUntil: messageThread.mute_until,
82
- isGroup: messageThread.thread_type == "GROUP",
83
- isSubscribed: messageThread.is_viewer_subscribed,
84
- isArchived: messageThread.has_viewer_archived,
85
- folder: messageThread.folder,
86
- cannotReplyReason: messageThread.cannot_reply_reason,
87
- eventReminders: messageThread.event_reminders
88
- ? messageThread.event_reminders.nodes.map(formatEventReminders)
89
- : null,
90
- emoji: messageThread.customization_info
91
- ? messageThread.customization_info.emoji
92
- : null,
93
- color:
94
- messageThread.customization_info &&
95
- messageThread.customization_info.outgoing_bubble_color
96
- ? messageThread.customization_info.outgoing_bubble_color.slice(2)
97
- : null,
98
- nicknames:
99
- messageThread.customization_info &&
100
- messageThread.customization_info.participant_customizations
101
- ? messageThread.customization_info.participant_customizations.reduce(
102
- function(res, val) {
103
- if (val.nickname) res[val.participant_id] = val.nickname;
104
- return res;
105
- },
106
- {}
107
- )
108
- : {},
109
- adminIDs: messageThread.thread_admins,
110
- approvalMode: Boolean(messageThread.approval_mode),
111
- approvalQueue: messageThread.group_approval_queue.nodes.map(a => ({
112
- inviterID: a.inviter.id,
113
- requesterID: a.requester.id,
114
- timestamp: a.request_timestamp,
115
- request_source: a.request_source // @Undocumented
116
- })),
117
-
118
- // @Undocumented
119
- reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
120
- mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
121
- isPinProtected: messageThread.is_pin_protected,
122
- relatedPageThread: messageThread.related_page_thread,
123
-
124
- // @Legacy
125
- name: messageThread.name,
126
- snippet: snippetText,
127
- snippetSender: snippetID,
128
- snippetAttachments: [],
129
- serverTimestamp: messageThread.updated_time_precise,
130
- imageSrc: messageThread.image ? messageThread.image.uri : null,
131
- isCanonicalUser: messageThread.is_canonical_neo_user,
132
- isCanonical: messageThread.thread_type != "GROUP",
133
- recipientsLoadable: true,
134
- hasEmailParticipant: false,
135
- readOnly: false,
136
- canReply: messageThread.cannot_reply_reason == null,
137
- lastMessageTimestamp: messageThread.last_message
138
- ? messageThread.last_message.timestamp_precise
139
- : null,
140
- lastMessageType: "message",
141
- lastReadTimestamp: lastReadTimestamp,
142
- threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
143
- TimeCreate: Date.now(),
144
- TimeUpdate: Date.now()
145
- };
146
- }
147
-
148
- const MAX_ARRAY_LENGTH = 6; //safe
149
- var Request_Update_Time = 0;
150
- var updateInterval;
151
- var updateTimeout;
152
- let Queues = [];
153
-
154
- let onetimecook = false
155
-
156
- function addToQueues(num) {
157
- const existingArray = Queues.some(subArr => subArr.some(obj => obj.threadID == num.threadID));
158
-
159
- if (!existingArray) {
160
- if (Queues.length > 0 && Queues[Queues.length - 1].length === MAX_ARRAY_LENGTH) {
161
- Queues.push([num]);
162
- } else {
163
- const lastArray = Queues.length > 0 ? Queues[Queues.length - 1] : [];
164
- lastArray.push(num);
165
-
166
- if (Queues.length === 0) {
167
- Queues.push(lastArray);
168
- }
169
- }
170
- }
171
- }
172
-
173
-
174
- module.exports = function(defaultFuncs, api, ctx) {
175
-
176
- var { createData,getData,hasData,updateData, getAll } = require('../Extra/ExtraGetThread');
177
- var Database = require('../Extra/Database');
178
-
179
- return async function getThreadInfoGraphQL(threadID, callback) {
180
- var resolveFunc = function(){};
181
- var rejectFunc = function(){};
182
- var returnPromise = new Promise(function (resolve, reject) {
183
- resolveFunc = resolve;
184
- rejectFunc = reject;
185
- });
186
-
187
- if (utils.getType(callback) != "Function" && utils.getType(callback) != "AsyncFunction") {
188
- callback = function (err, data) {
189
- if (err) {
190
- return rejectFunc(err);
191
- }
192
- resolveFunc(data);
193
- };
194
- }
195
-
196
- if (utils.getType(threadID) !== "Array") threadID = [threadID];
197
-
198
-
199
- if (utils.getType(global.Fca.Data.Userinfo) == "Array" || global.Fca.Data.Userinfo == undefined) global.Fca.Data.Userinfo = new Map();
200
-
201
- const updateUserInfo = (threadInfo) => {
202
- if (!global.Fca.Data.Userinfo) {
203
- global.Fca.Data.Userinfo = new Map();
204
- }
205
-
206
- threadInfo.forEach(thread => {
207
- const userInfo = thread.userInfo;
208
-
209
- if (Array.isArray(userInfo)) {
210
- const userInfoMap = new Map(userInfo.map(user => [user.id, user]));
211
- for (const [id, user] of userInfoMap) {
212
- global.Fca.Data.Userinfo.set(id, user);
213
- }
214
- }
215
- });
216
- };
217
-
218
- const getMultiInfo = async function (threadIDs) {
219
- let form = {};
220
- let tempThreadInf = [];
221
- threadIDs.forEach((x,y) => {
222
- form["o" + y] = {
223
- doc_id: "3449967031715030",
224
- query_params: { id: x, message_limit: 0, load_messages: false, load_read_receipts: false, before: null }
225
- };
226
- });
227
- let Submit = { queries: JSON.stringify(form), batch_name: "MessengerGraphQLThreadFetcher" };
228
-
229
- const promise = new Promise((resolve, reject) => {
230
- defaultFuncs.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, Submit)
231
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
232
- .then(resData => {
233
- if (resData.error || resData[resData.length - 1].error_results !== 0) throw "Lỗi: getThreadInfoGraphQL Có Thể Do Bạn Spam Quá Nhiều";
234
- resData = resData.slice(0, -1).sort((a, b) => Object.keys(a)[0].localeCompare(Object.keys(b)[0]));
235
- resData.forEach((x, y) => tempThreadInf.push(formatThreadGraphQLResponse(x["o" + y].data)));
236
- return resolve({
237
- Success: true,
238
- Data: tempThreadInf
239
- });
240
- })
241
- .catch(() => {
242
- reject({ Success: false, Data: '' })
243
- });
244
- })
245
-
246
- return await promise;
247
- }
248
-
249
- const formatAndUpdateData = (AllThreadInfo) => {
250
- try {
251
- AllThreadInfo.forEach(threadInf => { updateData(threadInf.threadID, threadInf); })
252
- updateUserInfo(AllThreadInfo) // [ {}, {} ]
253
-
254
- } catch (e) {
255
- console.log(e);
256
- }
257
- }
258
-
259
- const formatAndCreateData = (AllThreadInfo) => {
260
- try {
261
- AllThreadInfo.forEach(threadInf => { createData(threadInf.threadID, threadInf); })
262
- updateUserInfo(AllThreadInfo) // [ {}, {} ]
263
-
264
- } catch (e) {
265
- console.log(e);
266
- }
267
- }
268
-
269
- const checkAverageStaticTimestamp = function (avgTimeStamp) {
270
- const DEFAULT_UPDATE_TIME = 900 * 1000; //thời gian cập nhật tối đa + với thời gian trung bình của tổng request 1 mảng
271
- //khi request phút thứ 3, 1 req phút thứ 7, 1 req ở phút thứ 10, vậy trung bình là (3+7+1) / time.length (3) + với 15p = tg trung bình để cập nhật 1 mảng
272
- const MAXIMUM_ERROR_TIME = 10 * 1000;
273
- return { //khi check = false thì cần cập nhật vì đã hơn thời gian tb + 15p
274
- Check: (parseInt(avgTimeStamp) + parseInt(DEFAULT_UPDATE_TIME)) + parseInt(MAXIMUM_ERROR_TIME) >= Date.now(), // đây avgTimeStamp thời gian cố định của 1 mảng queue khi đầy
275
- timeLeft: (parseInt(avgTimeStamp) + parseInt(DEFAULT_UPDATE_TIME)) - Date.now() + parseInt(MAXIMUM_ERROR_TIME)
276
- }
277
- }
278
-
279
- const autoCheckAndUpdateRecallTime = () => {
280
- let holdTime = [];
281
- let oneTimeCall = false;
282
- //lấy tất cả trung bình thời gian của tất cả mảng và tìm thời gian còn lại ngắn nhất, nếu có sẵn id cần cập nhật thì cập nhật ngày lập tức
283
- Queues.forEach((i, index) => {
284
- // [ { threadID, TimeCreate }, {} ]
285
- const averageTimestamp = Math.round(i.reduce((acc, obj) => acc + obj.TimeCreate, 0) / i.length);
286
- const DataAvg = checkAverageStaticTimestamp(averageTimestamp);
287
- if (DataAvg.Check) {
288
- //cần chờ
289
- // holdTime.push(DataAvg.timeLeft);
290
- //cho thi cho 10s sau check lai roi cho tiep nhe =))
291
- }
292
- else {
293
- oneTimeCall = true;
294
- }
295
- });
296
-
297
- if (oneTimeCall) autoUpdateData(); // cập nhật ngay, nhin la biet tot hon hold roi =))
298
-
299
- // if (holdTime.length >= 1) {
300
- // holdTime.sort((a,b) => a - b) //low to high time
301
- // if (holdTime[0] > Request_Update_Time) {
302
- // Request_Update_Time = holdTime[0];
303
- // clearInterval(updateInterval);
304
- // updateInterval = setInterval(() => { autoUpdateData(); }, holdTime[0])
305
- // }
306
- // }
307
-
308
- //hold lam cai cho gi khi ta co check lien tuc 10s 1 lan 😔
309
-
310
- const MAXIMUM_RECALL_TIME = 30 * 1000;
311
- clearTimeout(updateTimeout);
312
- updateTimeout = setTimeout(() => { autoCheckAndUpdateRecallTime(); }, MAXIMUM_RECALL_TIME)
313
- }
314
-
315
- const autoUpdateData = async function() {
316
- //[ [ {}, {} ], [ {}, {} ] ]
317
- let doUpdate = [];
318
- let holdTime = [];
319
-
320
- Queues.forEach((i, index) => {
321
- // [ {}, {} ]
322
- const averageTimestamp = Math.round(i.reduce((acc, obj) => acc + obj.TimeCreate, 0) / i.length);
323
- // thời gian trung bình của 1 mảng từ lúc bắt đầu request lần đầu, cần + thêm thời gian cố định là 15p !
324
-
325
- const DataAvg = checkAverageStaticTimestamp(averageTimestamp)
326
- if (DataAvg.Check) {
327
- // chờ tiếp
328
- }
329
- else {
330
- // đã hơn thời gian 15p
331
- doUpdate.push(i) // [ {}, {} ]
332
- Queues.splice(index, 1); //đạt điều kiện nên xoá để tý nó tự thêm 💀
333
- }
334
-
335
- });
336
-
337
- if (doUpdate.length >= 1) {
338
- // maybe [ [ {}, {} ] [ {}, {} ] ]
339
- let ids = []; // [ id, id ]
340
- doUpdate.forEach(i => {
341
- //[ {} {} ]
342
- const onlyThreadID = [...new Set(i.map(obj => obj.threadID))]; // [ id1, id2 ]
343
- ids.push(onlyThreadID) //[ [ id1, id2 ] ]
344
- })
345
-
346
- // [ [ id1, id2 ],[ id1, id2 ] ] 5 per arr
347
-
348
- ids.forEach(async function(i) {
349
- const dataResp = await getMultiInfo(i);
350
- if (dataResp.Success == true) {
351
- let MultiThread = dataResp.Data;
352
- formatAndUpdateData(MultiThread)
353
- }
354
- else {
355
- global.Fca.Require.logger.Warning('CANT NOT GET THREADINFO 💀 MAYBE U HAS BEEN BLOCKED FROM FACEBOOK');
356
- }
357
- })
358
- }
359
- }
360
-
361
- const createOrTakeDataFromDatabase = async (threadIDs) => {
362
- let inDb = []; //NOTE: xử lý resp thành 1 mảng nếu có nhiều hơn 1 threadID và obj nếu 1 threadID
363
- let inFastArr = [];
364
- let createNow = [];
365
- let cbThreadInfos = [];
366
- // kiểm tra và phân ra 2 loại 1 là chưa có 2 là có =))
367
- // kiểm tra
368
-
369
- threadIDs.forEach(id => {
370
- // id, id ,id
371
- hasData(id) == true ? inDb.push(id) : createNow.push(id)
372
- });
373
-
374
- if (inDb.length >= 1) {
375
- let threadInfos = inDb.map(id => getData(id));
376
- cbThreadInfos = cbThreadInfos.concat(threadInfos);
377
- updateUserInfo(threadInfos);
378
-
379
- //request update queue
380
- threadInfos.forEach(i => addToQueues({ threadID: i.threadID, TimeCreate: Date.now() }));
381
- }
382
- if (createNow.length >= 1) {
383
- //5 data per chunk []
384
- const chunkSize = 5;
385
- const totalChunk = []; // [ [ id, id ], [ id,id ] ]
386
-
387
- for (let i = 0; i < createNow.length; i += chunkSize) {
388
- const chunk = createNow.slice(i, i + chunkSize);
389
- totalChunk.push(chunk);
390
- }
391
-
392
- for (let i of totalChunk) {
393
- //i = [ id,id ]
394
- const newThreadInf = await getMultiInfo(i); // always [ {} ] or [ {}, {} ]
395
- if (newThreadInf.Success == true) {
396
- let MultiThread = newThreadInf.Data;
397
- formatAndCreateData(MultiThread)
398
- cbThreadInfos = cbThreadInfos.concat(MultiThread)
399
-
400
- //request update queue
401
- MultiThread.forEach(i => addToQueues({ threadID: i.threadID, TimeCreate: Date.now() }));
402
- }
403
- else {
404
- global.Fca.Require.logger.Warning('CANT NOT GET THREADINFO 💀 MAYBE U HAS BEEN BLOCKED FROM FACEBOOK');
405
- }
406
- }
407
- }
408
- return cbThreadInfos.length == 1 ? callback(null, cbThreadInfos[0]) : callback(null, cbThreadInfos)
409
- }
410
-
411
- if (global.Fca.Data.Already != true) {
412
- global.Fca.Data.Already = true;
413
- autoCheckAndUpdateRecallTime();
414
- setInterval(function(){
415
- const MapToArray = Array.from(global.Fca.Data.Userinfo, ([name, value]) => (value));
416
- Database(true).set('UserInfo', MapToArray);
417
- }, 420 * 1000);
418
- }
419
-
420
- await createOrTakeDataFromDatabase(threadID);
421
-
422
- return returnPromise;
423
- };
1
+ /* eslint-disable linebreak-style */
2
+ "use strict";
3
+
4
+ var utils = require("../utils");
5
+ // tương lai đi rồi fix ahahha
6
+ function formatEventReminders(reminder) {
7
+ return {
8
+ reminderID: reminder.id,
9
+ eventCreatorID: reminder.lightweight_event_creator.id,
10
+ time: reminder.time,
11
+ eventType: reminder.lightweight_event_type.toLowerCase(),
12
+ locationName: reminder.location_name,
13
+ // @TODO verify this
14
+ locationCoordinates: reminder.location_coordinates,
15
+ locationPage: reminder.location_page,
16
+ eventStatus: reminder.lightweight_event_status.toLowerCase(),
17
+ note: reminder.note,
18
+ repeatMode: reminder.repeat_mode.toLowerCase(),
19
+ eventTitle: reminder.event_title,
20
+ triggerMessage: reminder.trigger_message,
21
+ secondsToNotifyBefore: reminder.seconds_to_notify_before,
22
+ allowsRsvp: reminder.allows_rsvp,
23
+ relatedEvent: reminder.related_event,
24
+ members: reminder.event_reminder_members.edges.map(function(member) {
25
+ return {
26
+ memberID: member.node.id,
27
+ state: member.guest_list_state.toLowerCase()
28
+ };
29
+ })
30
+ };
31
+ }
32
+
33
+ function formatThreadGraphQLResponse(data) {
34
+ try{
35
+ var messageThread = data.message_thread;
36
+ } catch (err){
37
+ console.error("GetThreadInfoGraphQL", "Can't get this thread info!");
38
+ return {err: err};
39
+ }
40
+ var threadID = messageThread.thread_key.thread_fbid
41
+ ? messageThread.thread_key.thread_fbid
42
+ : messageThread.thread_key.other_user_id;
43
+
44
+ // Remove me
45
+ var lastM = messageThread.last_message;
46
+ var snippetID =
47
+ lastM &&
48
+ lastM.nodes &&
49
+ lastM.nodes[0] &&
50
+ lastM.nodes[0].message_sender &&
51
+ lastM.nodes[0].message_sender.messaging_actor
52
+ ? lastM.nodes[0].message_sender.messaging_actor.id
53
+ : null;
54
+ var snippetText =
55
+ lastM && lastM.nodes && lastM.nodes[0] ? lastM.nodes[0].snippet : null;
56
+ var lastR = messageThread.last_read_receipt;
57
+ var lastReadTimestamp =
58
+ lastR && lastR.nodes && lastR.nodes[0] && lastR.nodes[0].timestamp_precise
59
+ ? lastR.nodes[0].timestamp_precise
60
+ : null;
61
+
62
+ return {
63
+ threadID: threadID,
64
+ threadName: messageThread.name,
65
+ participantIDs: messageThread.all_participants.edges.map(d => d.node.messaging_actor.id),
66
+ userInfo: messageThread.all_participants.edges.map(d => ({
67
+ id: d.node.messaging_actor.id,
68
+ name: d.node.messaging_actor.name,
69
+ firstName: d.node.messaging_actor.short_name,
70
+ vanity: d.node.messaging_actor.username,
71
+ thumbSrc: d.node.messaging_actor.big_image_src.uri,
72
+ profileUrl: d.node.messaging_actor.big_image_src.uri,
73
+ gender: d.node.messaging_actor.gender,
74
+ type: d.node.messaging_actor.__typename,
75
+ isFriend: d.node.messaging_actor.is_viewer_friend,
76
+ isBirthday: !!d.node.messaging_actor.is_birthday //not sure?
77
+ })),
78
+ unreadCount: messageThread.unread_count,
79
+ messageCount: messageThread.messages_count,
80
+ timestamp: messageThread.updated_time_precise,
81
+ muteUntil: messageThread.mute_until,
82
+ isGroup: messageThread.thread_type == "GROUP",
83
+ isSubscribed: messageThread.is_viewer_subscribed,
84
+ isArchived: messageThread.has_viewer_archived,
85
+ folder: messageThread.folder,
86
+ cannotReplyReason: messageThread.cannot_reply_reason,
87
+ eventReminders: messageThread.event_reminders
88
+ ? messageThread.event_reminders.nodes.map(formatEventReminders)
89
+ : null,
90
+ emoji: messageThread.customization_info
91
+ ? messageThread.customization_info.emoji
92
+ : null,
93
+ color:
94
+ messageThread.customization_info &&
95
+ messageThread.customization_info.outgoing_bubble_color
96
+ ? messageThread.customization_info.outgoing_bubble_color.slice(2)
97
+ : null,
98
+ nicknames:
99
+ messageThread.customization_info &&
100
+ messageThread.customization_info.participant_customizations
101
+ ? messageThread.customization_info.participant_customizations.reduce(
102
+ function(res, val) {
103
+ if (val.nickname) res[val.participant_id] = val.nickname;
104
+ return res;
105
+ },
106
+ {}
107
+ )
108
+ : {},
109
+ adminIDs: messageThread.thread_admins,
110
+ approvalMode: Boolean(messageThread.approval_mode),
111
+ approvalQueue: messageThread.group_approval_queue.nodes.map(a => ({
112
+ inviterID: a.inviter.id,
113
+ requesterID: a.requester.id,
114
+ timestamp: a.request_timestamp,
115
+ request_source: a.request_source // @Undocumented
116
+ })),
117
+
118
+ // @Undocumented
119
+ reactionsMuteMode: messageThread.reactions_mute_mode.toLowerCase(),
120
+ mentionsMuteMode: messageThread.mentions_mute_mode.toLowerCase(),
121
+ isPinProtected: messageThread.is_pin_protected,
122
+ relatedPageThread: messageThread.related_page_thread,
123
+
124
+ // @Legacy
125
+ name: messageThread.name,
126
+ snippet: snippetText,
127
+ snippetSender: snippetID,
128
+ snippetAttachments: [],
129
+ serverTimestamp: messageThread.updated_time_precise,
130
+ imageSrc: messageThread.image ? messageThread.image.uri : null,
131
+ isCanonicalUser: messageThread.is_canonical_neo_user,
132
+ isCanonical: messageThread.thread_type != "GROUP",
133
+ recipientsLoadable: true,
134
+ hasEmailParticipant: false,
135
+ readOnly: false,
136
+ canReply: messageThread.cannot_reply_reason == null,
137
+ lastMessageTimestamp: messageThread.last_message
138
+ ? messageThread.last_message.timestamp_precise
139
+ : null,
140
+ lastMessageType: "message",
141
+ lastReadTimestamp: lastReadTimestamp,
142
+ threadType: messageThread.thread_type == "GROUP" ? 2 : 1,
143
+ TimeCreate: Date.now(),
144
+ TimeUpdate: Date.now()
145
+ };
146
+ }
147
+
148
+ const MAX_ARRAY_LENGTH = 6; //safe
149
+ var Request_Update_Time = 0;
150
+ var updateInterval;
151
+ var updateTimeout;
152
+ let Queues = [];
153
+
154
+ let onetimecook = false
155
+
156
+ function addToQueues(num) {
157
+ const existingArray = Queues.some(subArr => subArr.some(obj => obj.threadID == num.threadID));
158
+
159
+ if (!existingArray) {
160
+ if (Queues.length > 0 && Queues[Queues.length - 1].length === MAX_ARRAY_LENGTH) {
161
+ Queues.push([num]);
162
+ } else {
163
+ const lastArray = Queues.length > 0 ? Queues[Queues.length - 1] : [];
164
+ lastArray.push(num);
165
+
166
+ if (Queues.length === 0) {
167
+ Queues.push(lastArray);
168
+ }
169
+ }
170
+ }
171
+ }
172
+
173
+
174
+ module.exports = function(defaultFuncs, api, ctx) {
175
+
176
+ var { createData,getData,hasData,updateData, getAll } = require('../Extra/ExtraGetThread');
177
+ var Database = require('../Extra/Database');
178
+
179
+ return async function getThreadInfoGraphQL(threadID, callback) {
180
+ var resolveFunc = function(){};
181
+ var rejectFunc = function(){};
182
+ var returnPromise = new Promise(function (resolve, reject) {
183
+ resolveFunc = resolve;
184
+ rejectFunc = reject;
185
+ });
186
+
187
+ if (utils.getType(callback) != "Function" && utils.getType(callback) != "AsyncFunction") {
188
+ callback = function (err, data) {
189
+ if (err) {
190
+ return rejectFunc(err);
191
+ }
192
+ resolveFunc(data);
193
+ };
194
+ }
195
+
196
+ if (utils.getType(threadID) !== "Array") threadID = [threadID];
197
+
198
+
199
+ if (utils.getType(global.Fca.Data.Userinfo) == "Array" || global.Fca.Data.Userinfo == undefined) global.Fca.Data.Userinfo = new Map();
200
+
201
+ const updateUserInfo = (threadInfo) => {
202
+ if (!global.Fca.Data.Userinfo) {
203
+ global.Fca.Data.Userinfo = new Map();
204
+ }
205
+
206
+ threadInfo.forEach(thread => {
207
+ const userInfo = thread.userInfo;
208
+
209
+ if (Array.isArray(userInfo)) {
210
+ const userInfoMap = new Map(userInfo.map(user => [user.id, user]));
211
+ for (const [id, user] of userInfoMap) {
212
+ global.Fca.Data.Userinfo.set(id, user);
213
+ }
214
+ }
215
+ });
216
+ };
217
+
218
+ const getMultiInfo = async function (threadIDs) {
219
+ let form = {};
220
+ let tempThreadInf = [];
221
+ threadIDs.forEach((x,y) => {
222
+ form["o" + y] = {
223
+ doc_id: "3449967031715030",
224
+ query_params: { id: x, message_limit: 0, load_messages: false, load_read_receipts: false, before: null }
225
+ };
226
+ });
227
+ let Submit = { queries: JSON.stringify(form), batch_name: "MessengerGraphQLThreadFetcher" };
228
+
229
+ const promise = new Promise((resolve, reject) => {
230
+ defaultFuncs.post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, Submit)
231
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
232
+ .then(resData => {
233
+ if (resData.error || resData[resData.length - 1].error_results !== 0) throw "Lỗi: getThreadInfoGraphQL Có Thể Do Bạn Spam Quá Nhiều";
234
+ resData = resData.slice(0, -1).sort((a, b) => Object.keys(a)[0].localeCompare(Object.keys(b)[0]));
235
+ resData.forEach((x, y) => tempThreadInf.push(formatThreadGraphQLResponse(x["o" + y].data)));
236
+ return resolve({
237
+ Success: true,
238
+ Data: tempThreadInf
239
+ });
240
+ })
241
+ .catch((err) => {
242
+ // Return error object instead of rejecting to prevent unhandled rejection
243
+ return resolve({ Success: false, Data: '', error: err?.message || 'Unknown error' });
244
+ });
245
+ })
246
+
247
+ return await promise;
248
+ }
249
+
250
+ const formatAndUpdateData = (AllThreadInfo) => {
251
+ try {
252
+ AllThreadInfo.forEach(threadInf => { updateData(threadInf.threadID, threadInf); })
253
+ updateUserInfo(AllThreadInfo) // [ {}, {} ]
254
+
255
+ } catch (e) {
256
+ console.log(e);
257
+ }
258
+ }
259
+
260
+ const formatAndCreateData = (AllThreadInfo) => {
261
+ try {
262
+ AllThreadInfo.forEach(threadInf => { createData(threadInf.threadID, threadInf); })
263
+ updateUserInfo(AllThreadInfo) // [ {}, {} ]
264
+
265
+ } catch (e) {
266
+ console.log(e);
267
+ }
268
+ }
269
+
270
+ const checkAverageStaticTimestamp = function (avgTimeStamp) {
271
+ const DEFAULT_UPDATE_TIME = 900 * 1000; //thời gian cập nhật tối đa + với thời gian trung bình của tổng request 1 mảng
272
+ //khi request phút thứ 3, 1 req ở phút thứ 7, 1 req ở phút thứ 10, vậy trung bình là (3+7+1) / time.length (3) + với 15p = tg trung bình để cập nhật 1 mảng
273
+ const MAXIMUM_ERROR_TIME = 10 * 1000;
274
+ return { //khi check = false thì cần cập nhật đã hơn thời gian tb + 15p
275
+ Check: (parseInt(avgTimeStamp) + parseInt(DEFAULT_UPDATE_TIME)) + parseInt(MAXIMUM_ERROR_TIME) >= Date.now(), // ở đây avgTimeStamp là thời gian cố định của 1 mảng queue khi đầy
276
+ timeLeft: (parseInt(avgTimeStamp) + parseInt(DEFAULT_UPDATE_TIME)) - Date.now() + parseInt(MAXIMUM_ERROR_TIME)
277
+ }
278
+ }
279
+
280
+ const autoCheckAndUpdateRecallTime = () => {
281
+ let holdTime = [];
282
+ let oneTimeCall = false;
283
+ //lấy tất cả trung bình thời gian của tất cả mảng và tìm thời gian còn lại ngắn nhất, nếu sẵn id cần cập nhật thì cập nhật ngày lập tức
284
+ Queues.forEach((i, index) => {
285
+ // [ { threadID, TimeCreate }, {} ]
286
+ const averageTimestamp = Math.round(i.reduce((acc, obj) => acc + obj.TimeCreate, 0) / i.length);
287
+ const DataAvg = checkAverageStaticTimestamp(averageTimestamp);
288
+ if (DataAvg.Check) {
289
+ //cần chờ
290
+ // holdTime.push(DataAvg.timeLeft);
291
+ //cho thi cho 10s sau check lai roi cho tiep nhe =))
292
+ }
293
+ else {
294
+ oneTimeCall = true;
295
+ }
296
+ });
297
+
298
+ if (oneTimeCall) autoUpdateData(); // cập nhật ngay, nhin la biet tot hon hold roi =))
299
+
300
+ // if (holdTime.length >= 1) {
301
+ // holdTime.sort((a,b) => a - b) //low to high time
302
+ // if (holdTime[0] > Request_Update_Time) {
303
+ // Request_Update_Time = holdTime[0];
304
+ // clearInterval(updateInterval);
305
+ // updateInterval = setInterval(() => { autoUpdateData(); }, holdTime[0])
306
+ // }
307
+ // }
308
+
309
+ //hold lam cai cho gi khi ta co check lien tuc 10s 1 lan 😔
310
+
311
+ const MAXIMUM_RECALL_TIME = 30 * 1000;
312
+ clearTimeout(updateTimeout);
313
+ updateTimeout = setTimeout(() => { autoCheckAndUpdateRecallTime(); }, MAXIMUM_RECALL_TIME)
314
+ }
315
+
316
+ const autoUpdateData = async function() {
317
+ //[ [ {}, {} ], [ {}, {} ] ]
318
+ let doUpdate = [];
319
+ let holdTime = [];
320
+
321
+ Queues.forEach((i, index) => {
322
+ // [ {}, {} ]
323
+ const averageTimestamp = Math.round(i.reduce((acc, obj) => acc + obj.TimeCreate, 0) / i.length);
324
+ // thời gian trung bình của 1 mảng từ lúc bắt đầu request lần đầu, cần + thêm thời gian cố định là 15p !
325
+
326
+ const DataAvg = checkAverageStaticTimestamp(averageTimestamp)
327
+ if (DataAvg.Check) {
328
+ // chờ tiếp
329
+ }
330
+ else {
331
+ // đã hơn thời gian 15p
332
+ doUpdate.push(i) // [ {}, {} ]
333
+ Queues.splice(index, 1); //đạt điều kiện nên xoá để tý nó tự thêm 💀
334
+ }
335
+
336
+ });
337
+
338
+ if (doUpdate.length >= 1) {
339
+ // maybe [ [ {}, {} ] [ {}, {} ] ]
340
+ let ids = []; // [ id, id ]
341
+ doUpdate.forEach(i => {
342
+ //[ {} {} ]
343
+ const onlyThreadID = [...new Set(i.map(obj => obj.threadID))]; // [ id1, id2 ]
344
+ ids.push(onlyThreadID) //[ [ id1, id2 ] ]
345
+ })
346
+
347
+ // [ [ id1, id2 ],[ id1, id2 ] ] 5 per arr
348
+
349
+ ids.forEach(async function(i) {
350
+ const dataResp = await getMultiInfo(i);
351
+ if (dataResp.Success == true) {
352
+ let MultiThread = dataResp.Data;
353
+ formatAndUpdateData(MultiThread)
354
+ }
355
+ else {
356
+ global.Fca.Require.logger.Warning('CANT NOT GET THREADINFO 💀 MAYBE U HAS BEEN BLOCKED FROM FACEBOOK');
357
+ }
358
+ })
359
+ }
360
+ }
361
+
362
+ const createOrTakeDataFromDatabase = async (threadIDs) => {
363
+ let inDb = []; //NOTE: xử lý resp thành 1 mảng nếu có nhiều hơn 1 threadID và obj nếu 1 threadID
364
+ let inFastArr = [];
365
+ let createNow = [];
366
+ let cbThreadInfos = [];
367
+ // kiểm tra và phân ra 2 loại 1 là chưa có 2 là có =))
368
+ // kiểm tra
369
+
370
+ threadIDs.forEach(id => {
371
+ // id, id ,id
372
+ hasData(id) == true ? inDb.push(id) : createNow.push(id)
373
+ });
374
+
375
+ if (inDb.length >= 1) {
376
+ let threadInfos = inDb.map(id => getData(id));
377
+ cbThreadInfos = cbThreadInfos.concat(threadInfos);
378
+ updateUserInfo(threadInfos);
379
+
380
+ //request update queue
381
+ threadInfos.forEach(i => addToQueues({ threadID: i.threadID, TimeCreate: Date.now() }));
382
+ }
383
+ if (createNow.length >= 1) {
384
+ //5 data per chunk []
385
+ const chunkSize = 5;
386
+ const totalChunk = []; // [ [ id, id ], [ id,id ] ]
387
+
388
+ for (let i = 0; i < createNow.length; i += chunkSize) {
389
+ const chunk = createNow.slice(i, i + chunkSize);
390
+ totalChunk.push(chunk);
391
+ }
392
+
393
+ for (let i of totalChunk) {
394
+ //i = [ id,id ]
395
+ const newThreadInf = await getMultiInfo(i); // always [ {} ] or [ {}, {} ]
396
+ if (newThreadInf.Success == true) {
397
+ let MultiThread = newThreadInf.Data;
398
+ formatAndCreateData(MultiThread)
399
+ cbThreadInfos = cbThreadInfos.concat(MultiThread)
400
+
401
+ //request update queue
402
+ MultiThread.forEach(i => addToQueues({ threadID: i.threadID, TimeCreate: Date.now() }));
403
+ }
404
+ else {
405
+ global.Fca.Require.logger.Warning('CANT NOT GET THREADINFO 💀 MAYBE U HAS BEEN BLOCKED FROM FACEBOOK');
406
+ }
407
+ }
408
+ }
409
+ return cbThreadInfos.length == 1 ? callback(null, cbThreadInfos[0]) : callback(null, cbThreadInfos)
410
+ }
411
+
412
+ if (global.Fca.Data.Already != true) {
413
+ global.Fca.Data.Already = true;
414
+ autoCheckAndUpdateRecallTime();
415
+ setInterval(function(){
416
+ const MapToArray = Array.from(global.Fca.Data.Userinfo, ([name, value]) => (value));
417
+ Database(true).set('UserInfo', MapToArray);
418
+ }, 420 * 1000);
419
+ }
420
+
421
+ await createOrTakeDataFromDatabase(threadID);
422
+
423
+ return returnPromise;
424
+ };
424
425
  };