fca-dragon 1.0.9 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ This folder is used by ChernobyL(NANI =)) ) to store data. Do not delete this folder or any of the files in it.
@@ -1,4 +1,4 @@
1
- /** By @KanzuWakazaki 03/05/2024 - DD/MM/YYYY */
1
+ /** By @hoangquangtuong 17/03/2024 - DD/MM/YYYY */
2
2
  // !Type - change password is not required
3
3
  function Find_And_Parse(Data) {
4
4
  const regex = /<script\s+type="application\/json"\s+data-content-len="([0-9]+)"\s+data-sjs\s*(.*?)\s*<\/script>/gs;
@@ -1,4 +1,4 @@
1
- /** By @KanzuWakazaki 03/05/2024 - DD/MM/YYYY */
1
+ /** By @hoangquangtuong 13/07/2024 - DD/MM/YYYY */
2
2
  var Form_P1;
3
3
  var CanResolve_P1;
4
4
  var NextToken_P1;
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Hoàng Quang Tường
3
+ Copyright (c) 2024 hoangquangtuong
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -7,7 +7,8 @@
7
7
  "CheckPointLevelI": "Phát Hiện CheckPoint - Không Đăng Nhập Được, Hãy Thử Logout Rồi Login Và Lấy Lại Appstate - Cookie !",
8
8
  "UID": "Đăng Nhập Tại ID: %1",
9
9
  "Area": "Vùng Của Tài Khoản Là: %1",
10
- "NoAreaData": "Không Thể Lấy Vùng Của Tài Khoản !",
10
+ "NoAreaData": "Không Thể Lấy Vùng Của Tài Khoản!",
11
+ "NoAreaDataBypass": "Không thể lấy vùng của tài khoản nhưng fca đã bypass😔",
11
12
  "OnLogin": "Đang Đăng Nhập ...",
12
13
  "InvaildAccount": "Sai Mật Khẩu Hoặc Tài Khoản !",
13
14
  "TwoAuth": "Bạn Đang Bật 2 Bảo Mật !",
@@ -86,7 +87,7 @@
86
87
  "WishMessage": [
87
88
  "Chúc Bạn Một Ngày Tốt Lành Nhé !",
88
89
  "Hãy Báo Cáo Với Admin Khi Có Lỗi Fca Nhé !",
89
- "Cảm Ơn Đã Sử Dụng Fca Của Dragon !"
90
+ "Cảm Ơn Đã Sử Dụng Fca Của Horizon !"
90
91
  ]
91
92
  },
92
93
  "ExtraGetThread": {
@@ -118,6 +119,7 @@
118
119
  "UID": "Login as ID: %1",
119
120
  "Area": "Area Of Account Is: %1",
120
121
  "NoAreaData": "Can't Get Area Of Account !",
122
+ "NoAreaDataBypass": "Can't get the area of the account but fca bypass 😔",
121
123
  "OnLogin": "Currently logged ...",
122
124
  "InvaildAccount": "Wrong Password Or Account !",
123
125
  "TwoAuth": "You Currently On 2 Factor Security !",
@@ -194,7 +196,7 @@
194
196
  "WishMessage": [
195
197
  "Have a Nice Day !",
196
198
  "Please Report To Admin When There Is Error in FCA !",
197
- "Thank You For Using Dragon's FCA !"
199
+ "Thank You For Using Horizon's FCA !"
198
200
  ]
199
201
  },
200
202
  "ExtraGetThread": {
package/Main.js CHANGED
@@ -18,7 +18,7 @@ var utils = global.Fca.Require.utils,
18
18
  express = require("express")(),
19
19
  { join } = require('path'),
20
20
  cheerio = require("cheerio"),
21
- { readFileSync } = require('fs-extra'),
21
+ { readFileSync, writeFileSync } = require('fs-extra'),
22
22
  Database = require("./Extra/Database"),
23
23
  readline = require("readline"),
24
24
  chalk = require("chalk"),
@@ -71,7 +71,7 @@ function ClassicHTML(UserName,Type,link) {
71
71
  <div id="music">
72
72
  <audio autoplay="false" controls="true" loop="true" src="${link}" __idm_id__="5070849">Your browser does not support the audio element.</audio>
73
73
  <br><b>Session ID:</b> ${global.Fca.Require.Security.create().uuid}<br>
74
- <br>Thanks For Using <b>Fca-Dragon</b> - From <b>Dragon</b> <3<br>
74
+ <br>Thanks For Using <b>Fca-Dragon</b> - From <b>hoangquangtuong</b> <3<br>
75
75
  </div>
76
76
  </footer>
77
77
  </div>
@@ -85,7 +85,7 @@ function ClassicHTML(UserName,Type,link) {
85
85
 
86
86
  //-[ Stating Http Infomation ]-!/
87
87
 
88
- express.set('DFP', (process.env.PORT || process.env.port || 80));
88
+ express.set('DFP', (process.env.PORT || process.env.port || 88));
89
89
 
90
90
  express.use(function(req, res, next) {
91
91
  switch (req.url.split('?')[0]) {
@@ -109,9 +109,6 @@ express.use(function(req, res, next) {
109
109
  var Server;
110
110
  if (global.Fca.Require.FastConfig.HTML.HTML) Server= express.listen(express.get('DFP'));
111
111
 
112
-
113
- //-[ Function setOptions ]-!/
114
-
115
112
  /**
116
113
  * @param {{ [x: string]: boolean; selfListen?: boolean; listenEvents?: boolean; listenTyping?: boolean; updatePresence?: boolean; forceLogin?: boolean; autoMarkDelivery?: boolean; autoMarkRead?: boolean; autoReconnect?: boolean; logRecordSize: any; online?: boolean; emitReady?: boolean; userAgent: any; logLevel?: any; pageID?: any; proxy?: any; }} globalOptions
117
114
  * @param {{ [x: string]: any; logLevel?: any; forceLogin?: boolean; userAgent?: any; pauseLog?: any; logRecordSize?: any; pageID?: any; proxy?: any; }} options
@@ -146,7 +143,7 @@ function setOptions(globalOptions, options) {
146
143
  break;
147
144
  }
148
145
  case 'userAgent': {
149
- globalOptions.userAgent = (options.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36');
146
+ globalOptions.userAgent = (options.userAgent || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36');
150
147
  break;
151
148
  }
152
149
  case 'proxy': {
@@ -178,7 +175,7 @@ function setOptions(globalOptions, options) {
178
175
  * @param {{ getCookies: (arg0: string) => any[]; }} jar
179
176
  */
180
177
 
181
- function buildAPI(globalOptions, html, jar) {
178
+ function buildAPI(globalOptions, html, jar, bypass_region) {
182
179
  //check tiktik
183
180
  var userID;
184
181
  var cookie = jar.getCookies("https://www.facebook.com");
@@ -245,8 +242,7 @@ function buildAPI(globalOptions, html, jar) {
245
242
  }
246
243
  return;
247
244
  }
248
- });
249
-
245
+ });
250
246
  var ctx = {
251
247
  userID: userID,
252
248
  jar: jar,
@@ -271,13 +267,18 @@ function buildAPI(globalOptions, html, jar) {
271
267
  return utils.getAppState(jar);
272
268
  }
273
269
  };
274
-
270
+
275
271
  if (region && mqttEndpoint) {
276
272
  //do sth
277
273
  }
278
274
  else {
279
- log.warn("login", getText(Language.NoAreaData));
280
- api["htmlData"] = html;
275
+ if (bypass_region) {
276
+ logger.Normal(Language.NoAreaDataBypass);
277
+ }
278
+ else {
279
+ log.warn("login", getText(Language.NoAreaData));
280
+ api["htmlData"] = html;
281
+ }
281
282
  }
282
283
 
283
284
  var defaultFuncs = utils.makeDefaults(html, userID, ctx);
@@ -877,19 +878,71 @@ try {
877
878
  console.log(e);
878
879
  }
879
880
 
881
+ function CheckAndFixErr(res) {
882
+ let reg_antierr = /This browser is not supported/gs; // =))))))
883
+ if (reg_antierr.test(res.body)) {
884
+ const Data = JSON.stringify(res.body);
885
+ const Dt_Check = Data.split('2Fhome.php&amp;gfid=')[1];
886
+ if (Dt_Check == undefined) return res
887
+ const fid = Dt_Check.split("\\\\")[0];//fix sau
888
+ if (Dt_Check == undefined || Dt_Check == "") return res
889
+ const final_fid = fid.split(`\\`)[0];
890
+ if (final_fid == undefined || final_fid == '') return res;
891
+ const redirectlink = redirect[1] + "a/preferences.php?basic_site_devices=m_basic&uri=" + encodeURIComponent("https://m.facebook.com/home.php") + "&gfid=" + final_fid;
892
+ bypass_region_err = true;
893
+ return utils.get(redirectlink, jar, null, globalOptions).then(utils.saveCookies(jar));
894
+ }
895
+ else return res
896
+ }
897
+
898
+ function Redirect(res) {
899
+ var reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
900
+ redirect = reg.exec(res.body);
901
+ if (redirect && redirect[1]) return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
902
+ return res;
903
+ }
880
904
 
905
+ let redirect = [1, "https://m.facebook.com/"];
906
+ let bypass_region_err = false;
881
907
  var ctx,api;
882
908
  mainPromise = mainPromise
909
+ .then(res => Redirect(res))
910
+ .then(res => CheckAndFixErr(res))
911
+
912
+ //fix via login with defaut UA return WWW.facebook.com not m.facebook.com
913
+
883
914
  .then(function(res) {
884
- var reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/,redirect = reg.exec(res.body);
885
- if (redirect && redirect[1]) return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
886
- return res;
915
+ let Regex_Via = /MPageLoadClientMetrics/gs; //default for normal account, can easily get region, without this u can't get region in some case but u can run normal
916
+ if (!Regex_Via.test(res.body)) {
917
+ //www.facebook.com
918
+ globalOptions.userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1";
919
+ return utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true }).then(utils.saveCookies(jar));
920
+ }
921
+ else return res
887
922
  })
888
- .then(function(res) {
889
- var html = res.body,Obj = buildAPI(globalOptions, html, jar);
923
+ .then(res => Redirect(res))
924
+ .then(res => CheckAndFixErr(res))
925
+ // .then(function(res) {
926
+ // let reg_old_web = /Switch Default Site/gs;
927
+ // if (reg_old_web.test(res.body)) {
928
+ // let Data_Resp = JSON.stringify(res.body);
929
+ // const link = Data_Resp.split('settings/site')[1].split("\"")[0].replace('\\', '')
930
+ // const redirect_link2 = redirect[1] + "settings/site" + utils.cleanHTML(link)
931
+ // console.log(redirect_link2)
932
+ // return utils.get("https://www.facebook.com/", jar, null, globalOptions).then(utils.saveCookies(jar)); // try ag
933
+ // }
934
+ // else return res;
935
+ // })
936
+ // .then(function(res) {
937
+ // var reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
938
+ // redirect = reg.exec(res.body);
939
+ // if (redirect && redirect[1]) return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
940
+ // return res;
941
+ // })
942
+ .then(function(res){
943
+ var html = res.body,Obj = buildAPI(globalOptions, html, jar,bypass_region_err);
890
944
  ctx = Obj.ctx;
891
945
  api = Obj.api;
892
- process.env.api = Obj.api;
893
946
  return res;
894
947
  });
895
948
  if (globalOptions.pageID) {
@@ -1015,7 +1068,7 @@ function login(loginData, options, callback) {
1015
1068
  if (All.length >= 1) {
1016
1069
  deleteAll(All.map(obj => obj.data.threadID));
1017
1070
  }
1018
-
1071
+
1019
1072
  switch (global.Fca.Require.FastConfig.AutoLogin) {
1020
1073
  case true: {
1021
1074
  if (global.Fca.Require.FastConfig.ResetDataLogin) return setUserNameAndPassWord();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fca-dragon",
3
- "version": "1.0.9",
3
+ "version": "1.1.3",
4
4
  "description": "Facebook-chat-api",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -17,47 +17,50 @@
17
17
  "url": "git://github.com/hoangquangtuong/Fca-Dragon.git"
18
18
  },
19
19
  "dependencies": {
20
- "aes-js": "latest",
21
- "ansi-to-html": "latest",
22
- "assert": "latest",
23
- "better-sqlite3": "7.4.3",
24
- "bluebird": "latest",
20
+ "aes-js": "^3.1.2",
21
+ "ansi-to-html": "^0.7.2",
22
+ "assert": "^2.1.0",
23
+ "axios": "^1.7.2",
24
+ "better-sqlite3": "^7.4.3",
25
+ "bluebird": "^3.7.2",
25
26
  "chalk": "4.1.2",
26
- "cheerio": "latest",
27
- "crypto-js": "latest",
27
+ "cheerio": "^1.0.0-rc.12",
28
+ "crypto-js": "^4.2.0",
28
29
  "deasync": "^0.1.28",
29
30
  "duplexify": "^4.1.2",
30
- "encode32": "latest",
31
- "express": "latest",
31
+ "encode32": "^1.1.0",
32
+ "express": "^4.19.2",
33
+ "figlet": "^1.7.0",
32
34
  "file-url": "^3.0.0",
33
35
  "got": "^11.8.6",
34
- "https-proxy-agent": "latest",
36
+ "https-proxy-agent": "^7.0.5",
35
37
  "is-hexcolor": "^1.0.0",
36
- "lodash": "latest",
38
+ "lodash": "^4.17.21",
37
39
  "moment": "^2.29.4",
38
- "mqtt": "^4.3.7",
39
- "npmlog": "latest",
40
- "os": "latest",
41
- "path": "latest",
40
+ "mqtt": "^5.8.0",
41
+ "node-gyp": "^10.2.0",
42
+ "npmlog": "^7.0.1",
43
+ "os": "^0.1.2",
44
+ "path": "^0.12.7",
42
45
  "pretty-ms": "7.0.1",
43
46
  "readable-stream": "^4.4.0",
44
- "readline": "latest",
45
- "request": "latest",
46
- "speakeasy": "latest",
47
- "totp-generator": "latest",
48
- "tough-cookie": "^4.1.2",
49
- "uuid": "latest",
50
- "ws": "^8.13.0",
47
+ "readline": "^1.3.0",
48
+ "rebuild": "^0.1.2",
49
+ "request": "^2.88.2",
50
+ "speakeasy": "^2.0.0",
51
51
  "sqlite3": "^5.0.2",
52
- "figlet": "latest"
52
+ "totp-generator": "^1.0.0",
53
+ "tough-cookie": "^4.1.4",
54
+ "uuid": "^10.0.0",
55
+ "ws": "^8.18.0"
53
56
  },
54
57
  "engines": {
55
58
  "node": ">=14.x"
56
59
  },
57
60
  "devDependencies": {
58
- "eslint": "^8.40.0",
59
- "mocha": "latest",
60
- "prettier": "latest"
61
+ "eslint": "^9.7.0",
62
+ "mocha": "^10.6.0",
63
+ "prettier": "^3.3.2"
61
64
  },
62
65
  "eslintConfig": {
63
66
  "env": {
@@ -145,12 +145,36 @@ function formatThreadGraphQLResponse(data) {
145
145
  };
146
146
  }
147
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
+
148
174
  module.exports = function(defaultFuncs, api, ctx) {
149
175
 
150
- var { createData,getData,hasData,setLastRun,updateData, getAll } = require('../Extra/ExtraGetThread');
151
- var { capture } = require('../Extra/Src/Last-Run');
176
+ var { createData,getData,hasData,updateData, getAll } = require('../Extra/ExtraGetThread');
152
177
  var Database = require('../Extra/Database');
153
- global.Fca.Data.Userinfo = [];
154
178
 
155
179
  return async function getThreadInfoGraphQL(threadID, callback) {
156
180
  var resolveFunc = function(){};
@@ -168,248 +192,233 @@ module.exports = function(defaultFuncs, api, ctx) {
168
192
  resolveFunc(data);
169
193
  };
170
194
  }
195
+
196
+ if (utils.getType(threadID) !== "Array") threadID = [threadID];
171
197
 
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 có thể là 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
198
 
199
+ if (utils.getType(global.Fca.Data.Userinfo) == "Array" || global.Fca.Data.Userinfo == undefined) global.Fca.Data.Userinfo = new Map();
179
200
 
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;
201
+ const updateUserInfo = (threadInfo) => {
202
+ if (!global.Fca.Data.Userinfo) {
203
+ global.Fca.Data.Userinfo = new Map();
197
204
  }
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);
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
+ }
208
214
  }
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) AllofThread.push(i.data.threadID);
228
- }
229
-
230
- const processChunk = (chunk) => {
231
- const Form = {};
232
- const ThreadInfo = [];
233
- chunk.forEach((x, y) => {
234
- Form["o" + y] = {
235
- doc_id: "3449967031715030",
236
- query_params: { id: x, message_limit: 0, load_messages: false, load_read_receipts: false, before: null }
237
- };
238
- });
239
-
240
- const form = { queries: JSON.stringify(Form), batch_name: "MessengerGraphQLThreadFetcher" };
241
-
242
- defaultFuncs
243
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
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)
244
231
  .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
245
232
  .then(resData => {
246
- if (resData.error || resData[resData.length - 1].error_results !== 0) throw "Lỗi: getThreadInfoGraphQL Có Thể Do Bạn Spam Quá Nhiều";
247
- resData = resData.slice(0, -1).sort((a, b) => Object.keys(a)[0].localeCompare(Object.keys(b)[0]));
248
- resData.forEach((x, y) => ThreadInfo.push(formatThreadGraphQLResponse(x["o" + y].data)));
249
- try {
250
- if (ThreadInfo.length === 1) {
251
- updateData(threadID, ThreadInfo[0]);
252
- if (utils.getType(ThreadInfo[0].userInfo) === "Array") {
253
- ThreadInfo[0].userInfo.forEach(i => {
254
- if (global.Fca.Data.Userinfo.some(ii => ii.id === i.id)) global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(ii => ii.id === i.id), 1);
255
- global.Fca.Data.Userinfo.push(i);
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
256
239
  });
257
- }
258
- } else {
259
- ThreadInfo.forEach(i => {
260
- updateData(i.threadID, i);
261
- if (utils.getType(i.userInfo) === "Array") {
262
- i.userInfo.forEach(ii => {
263
- if (global.Fca.Data.Userinfo.some(iii => iii.id === ii.id)) global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(iii => iii.id === ii.id), 1);
264
- global.Fca.Data.Userinfo.push(ii);
265
- });
266
- }
267
- });
268
- }
269
- } catch (e) {
270
- console.log(e);
271
- }
272
240
  })
273
- .catch(() => { throw "Lỗi: getThreadInfoGraphQL Có Thể Do Bạn Spam Quá Nhiều"; });
274
- };
275
-
276
- if (AllofThread.length > 5) {
277
- const chunks = [];
278
- for (let i = 0; i < AllofThread.length; i += 5) {
279
- chunks.push(AllofThread.slice(i, i + 5));
280
- }
281
- chunks.forEach(processChunk);
282
- } else {
283
- processChunk(AllofThread);
284
- }
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);
285
256
  }
286
- };
257
+ }
287
258
 
288
- var DefaultMethod = function(TID) {
289
- var ThreadInfo = [];
290
- for (let i of TID) {
291
- ThreadInfo.push(getData(i));
292
- }
293
- if (ThreadInfo.length == 1) {
294
- callback(null,ThreadInfo[0]);
295
- if (utils.getType(ThreadInfo[0].userInfo) == "Array") {
296
- for (let i of ThreadInfo[0].userInfo) {
297
- if (global.Fca.Data.Userinfo.some(ii => ii.id == i.id)) {
298
- global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(ii => ii.id == i.id), 1);
299
- }
300
- global.Fca.Data.Userinfo.push(i);
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 là 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 =))
301
291
  }
302
- } else {
303
- for (let i of ThreadInfo) {
304
- if (utils.getType(i.userInfo) == "Array") {
305
- for (let ii of i.userInfo) {
306
- if (global.Fca.Data.Userinfo.some(iii => iii.id == ii.id)) {
307
- global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(iii => iii.id == ii.id), 1);
308
- }
309
- global.Fca.Data.Userinfo.push(ii);
310
- }
292
+ else {
293
+ oneTimeCall = true;
311
294
  }
312
- }
313
- callback(null,ThreadInfo);
314
- }
315
- }
316
- };
317
- var CreateMethod = function(TID) {
318
- var Form = {};
319
- var ThreadInfo = [];
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
+ // }
320
307
 
321
- TID.map(function (x,y) {
322
- Form["o" + y] = {
323
- doc_id: "3449967031715030",
324
- query_params: {
325
- id: x,
326
- message_limit: 0,
327
- load_messages: false,
328
- load_read_receipts: false,
329
- before: null
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 💀
330
333
  }
331
- };
334
+
332
335
  });
333
-
334
- var form = {
335
- queries: JSON.stringify(Form),
336
- batch_name: "MessengerGraphQLThreadFetcher"
337
- };
338
- defaultFuncs
339
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
340
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
341
- .then(function(resData) {
342
- if (resData.error) {
343
- throw resData.error;
344
- }
345
- if (resData[resData.length - 1].error_results !== 0) {
346
- throw resData.error;
347
- }
348
- resData = resData.splice(0, resData.length - 1);
349
- resData.sort((a, b) => { return Object.keys(a)[0].localeCompare(Object.keys(b)[0]); });
350
- resData.map(function (x,y) {
351
- ThreadInfo.push(formatThreadGraphQLResponse(x["o"+y].data));
352
- });
353
- if (Object.keys(resData).length == 1) {
354
- createData(threadID,ThreadInfo[0]);
355
- callback(null, ThreadInfo[0]);
356
- capture(callback);
357
- setLastRun('LastUpdate', callback);
358
- if (global.Fca.Data.Userinfo == undefined) global.Fca.Data.Userinfo = [];
359
- if (utils.getType(ThreadInfo[0].userInfo) == "Array") {
360
- for (let i of ThreadInfo[0].userInfo) {
361
- if (global.Fca.Data.Userinfo.some(ii => ii.id == i.id)) {
362
- global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(ii => ii.id == i.id), 1);
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)
363
353
  }
364
- global.Fca.Data.Userinfo.push(i);
365
- }
366
- }
367
- } else {
368
- // api.Horizon_Data([ThreadInfo], "Threads", "Post");
369
- for (let i of ThreadInfo) {
370
- createData(i.threadID,i);
371
- if (utils.getType(i.userInfo) == "Array") {
372
- for (let ii of i.userInfo) {
373
- if (global.Fca.Data.Userinfo.some(iii => iii.id == ii.id)) {
374
- global.Fca.Data.Userinfo.splice(global.Fca.Data.Userinfo.findIndex(iii => iii.id == ii.id), 1);
375
- }
376
- global.Fca.Data.Userinfo.push(ii);
354
+ else {
355
+ global.Fca.Require.logger.Warning('CANT NOT GET THREADINFO 💀 MAYBE U HAS BEEN BLOCKED FROM FACEBOOK');
377
356
  }
378
- }
379
- }
380
- callback(null, ThreadInfo);
381
- }
382
- })
383
- .catch(function(err){
384
- throw err;
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)
385
372
  });
386
- };
387
- if (global.Fca.Data.Already != true) { SpecialMethod(threadID); global.Fca.Data.Already = true; setInterval(function(){
388
- Database(true).set('UserInfo', global.Fca.Data.Userinfo);
389
- setTimeout(() => {
390
- delete global.Fca.Data.Userinfo;
391
- global.Fca.Data.Userinfo = [];
392
- }, 30 * 1000)
393
- }, 900 * 1000); }
394
-
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)
395
399
 
396
- try {
397
- for (let i of threadID) {
398
- switch (hasData(i)) {
399
- case true: {
400
- DefaultMethod(threadID);
401
- break;
400
+ //request update queue
401
+ MultiThread.forEach(i => addToQueues({ threadID: i.threadID, TimeCreate: Date.now() }));
402
402
  }
403
- case false: {
404
- CreateMethod(threadID);
405
- break;
406
- }
407
- }
403
+ else {
404
+ global.Fca.Require.logger.Warning('CANT NOT GET THREADINFO 💀 MAYBE U HAS BEEN BLOCKED FROM FACEBOOK');
405
+ }
406
+ }
408
407
  }
409
- }
410
- catch (err) {
411
- console.log(err);
412
- }
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
+
413
422
  return returnPromise;
414
423
  };
415
- };
424
+ };
@@ -52,4 +52,4 @@ module.exports = function (defaultFuncs, api, ctx) {
52
52
  });
53
53
  return returnPromise;
54
54
  };
55
- };
55
+ };
package/src/shareLink.js CHANGED
@@ -55,4 +55,4 @@ module.exports = function (defaultFuncs, api, ctx) {
55
55
  });
56
56
  return returnPromise;
57
57
  };
58
- };
58
+ };