aminul-new-fca 1.0.21 → 1.0.23

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.
@@ -12,7 +12,7 @@ jobs:
12
12
  - name: Setup Node.js
13
13
  uses: actions/setup-node@v2
14
14
  with:
15
- node-version: 16
15
+ node-version: 20
16
16
  registry-url: https://registry.npmjs.org
17
17
 
18
18
  - name: Publish to NPM
package/index.js CHANGED
@@ -1,11 +1,11 @@
1
- // reprogrammed by rui
2
- // credits to original owners
3
-
4
1
  "use strict";
5
2
 
6
- const utils = require("./utils");
7
3
  const fs = require("fs");
4
+ const path = require("path");
5
+ const request = require("request");
6
+ const cheerio = require("cheerio");
8
7
  const cron = require("node-cron");
8
+ const utils = require("./utils");
9
9
 
10
10
  let globalOptions = {};
11
11
  let ctx = null;
@@ -13,51 +13,45 @@ let _defaultFuncs = null;
13
13
  let api = null;
14
14
  let region;
15
15
 
16
- const errorRetrieving = "Error retrieving userID. This can be caused by a lot of things, including getting blocked by Facebook for logging in from an unknown location. Try logging in with a browser to verify.";
17
-
18
- const logging = (bool) => {
19
- utils.setLogging(bool);
20
- }
21
-
22
- async function setOptions(globalOptions_from,
23
- options = {}) {
24
- Object.keys(options).map((key) => {
16
+ // ================== OPTIONS ==================
17
+ async function setOptions(globalOptions_from, options = {}) {
18
+ Object.keys(options).forEach((key) => {
25
19
  switch (key) {
26
- case 'online':
20
+ case "online":
27
21
  globalOptions_from.online = Boolean(options.online);
28
22
  break;
29
- case 'selfListen':
23
+ case "selfListen":
30
24
  globalOptions_from.selfListen = Boolean(options.selfListen);
31
25
  break;
32
- case 'selfListenEvent':
26
+ case "selfListenEvent":
33
27
  globalOptions_from.selfListenEvent = options.selfListenEvent;
34
28
  break;
35
- case 'listenEvents':
29
+ case "listenEvents":
36
30
  globalOptions_from.listenEvents = Boolean(options.listenEvents);
37
31
  break;
38
- case 'pageID':
32
+ case "pageID":
39
33
  globalOptions_from.pageID = options.pageID.toString();
40
34
  break;
41
- case 'updatePresence':
35
+ case "updatePresence":
42
36
  globalOptions_from.updatePresence = Boolean(options.updatePresence);
43
37
  break;
44
- case 'forceLogin':
38
+ case "forceLogin":
45
39
  globalOptions_from.forceLogin = Boolean(options.forceLogin);
46
40
  break;
47
- case 'userAgent':
41
+ case "userAgent":
48
42
  globalOptions_from.userAgent = options.userAgent;
49
43
  break;
50
- case 'autoMarkDelivery':
44
+ case "autoMarkDelivery":
51
45
  globalOptions_from.autoMarkDelivery = Boolean(options.autoMarkDelivery);
52
46
  break;
53
- case 'autoMarkRead':
47
+ case "autoMarkRead":
54
48
  globalOptions_from.autoMarkRead = Boolean(options.autoMarkRead);
55
49
  break;
56
- case 'listenTyping':
50
+ case "listenTyping":
57
51
  globalOptions_from.listenTyping = Boolean(options.listenTyping);
58
52
  break;
59
- case 'proxy':
60
- if (typeof options.proxy != "string") {
53
+ case "proxy":
54
+ if (typeof options.proxy !== "string") {
61
55
  delete globalOptions_from.proxy;
62
56
  utils.setProxy();
63
57
  } else {
@@ -65,21 +59,23 @@ async function setOptions(globalOptions_from,
65
59
  utils.setProxy(globalOptions_from.proxy);
66
60
  }
67
61
  break;
68
- case 'autoReconnect':
62
+ case "autoReconnect":
69
63
  globalOptions_from.autoReconnect = Boolean(options.autoReconnect);
70
64
  break;
71
- case 'emitReady':
65
+ case "emitReady":
72
66
  globalOptions_from.emitReady = Boolean(options.emitReady);
73
67
  break;
74
- case 'randomUserAgent':
68
+ case "randomUserAgent":
75
69
  globalOptions_from.randomUserAgent = Boolean(options.randomUserAgent);
76
70
  if (globalOptions_from.randomUserAgent) {
77
71
  globalOptions_from.userAgent = utils.randomUserAgent();
78
- utils.warn("Random user agent enabled. This is an EXPERIMENTAL feature and I think this won't on some accounts. turn it on at your own risk. Contact the owner for more information about experimental features.");
79
- utils.warn("randomUserAgent", "UA selected:", globalOptions_from.userAgent);
72
+ console.warn(
73
+ "[ AMINUL-FCA ] Random user agent enabled. Using:",
74
+ globalOptions_from.userAgent
75
+ );
80
76
  }
81
77
  break;
82
- case 'bypassRegion':
78
+ case "bypassRegion":
83
79
  globalOptions_from.bypassRegion = options.bypassRegion;
84
80
  break;
85
81
  default:
@@ -89,41 +85,39 @@ async function setOptions(globalOptions_from,
89
85
  globalOptions = globalOptions_from;
90
86
  }
91
87
 
88
+ // ================== UPDATE DTSG ==================
92
89
  async function updateDTSG(res, appstate, userId) {
93
90
  try {
94
- const appstateCUser = (appstate.find(i => i.key == 'i_user') || appstate.find(i => i.key == 'c_user'))
91
+ const appstateCUser = (appstate.find(i => i.key === 'i_user') || appstate.find(i => i.key === 'c_user'));
95
92
  const UID = userId || appstateCUser.value;
96
- if (!res || !res.body) {
97
- throw new Error("Invalid response: Response body is missing.");
98
- }
93
+
94
+ if (!res || !res.body) throw new Error("Invalid response: Response body is missing.");
95
+
99
96
  const fb_dtsg = utils.getFrom(res.body, '["DTSGInitData",[],{"token":"', '","');
100
97
  const jazoest = utils.getFrom(res.body, 'jazoest=', '",');
98
+
101
99
  if (fb_dtsg && jazoest) {
102
100
  const filePath = 'fb_dtsg_data.json';
103
101
  let existingData = {};
104
102
  if (fs.existsSync(filePath)) {
105
- const fileContent = fs.readFileSync(filePath, 'utf8');
106
- existingData = JSON.parse(fileContent);
103
+ existingData = JSON.parse(fs.readFileSync(filePath, "utf8"));
107
104
  }
108
- existingData[UID] = {
109
- fb_dtsg,
110
- jazoest
111
- };
112
- fs.writeFileSync(filePath, JSON.stringify(existingData, null, 2), 'utf8');
105
+ existingData[UID] = { fb_dtsg, jazoest };
106
+ fs.writeFileSync(filePath, JSON.stringify(existingData, null, 2), "utf8");
113
107
  }
114
108
  return res;
115
109
  } catch (error) {
116
- utils.error(`Error updating DTSG for user ${userId}: ${error.message}`);
117
- return;
110
+ console.error("[ AMINUL-FCA ] updateDTSG error:", error.message);
118
111
  }
119
112
  }
120
113
 
121
-
114
+ // ================== BYPASS AUTO BEHAVIOR ==================
122
115
  let isBehavior = false;
123
116
  async function bypassAutoBehavior(resp, jar, appstate, ID) {
124
117
  try {
125
- const appstateCUser = (appstate.find(i => i.key == 'c_user') || appstate.find(i => i.key == 'i_user'))
118
+ const appstateCUser = (appstate.find(i => i.key === 'c_user') || appstate.find(i => i.key === 'i_user'));
126
119
  const UID = ID || appstateCUser.value;
120
+
127
121
  const FormBypass = {
128
122
  av: UID,
129
123
  fb_api_caller_class: "RelayModern",
@@ -131,388 +125,82 @@ async function bypassAutoBehavior(resp, jar, appstate, ID) {
131
125
  variables: JSON.stringify({}),
132
126
  server_timestamps: true,
133
127
  doc_id: 6339492849481770
134
- }
128
+ };
129
+
135
130
  const kupal = () => {
136
- utils.warn(`We suspect automated behavior on account ${UID}. Some accounts might experience auto logout, and you need to resubmit your appstate again every automated behavior detection.`);
131
+ console.warn("[ AMINUL-FCA ] Automated behavior detected on account", UID);
137
132
  if (!isBehavior) isBehavior = true;
138
133
  };
139
- if (resp) {
140
- if (resp.request.uri && resp.request.uri.href.includes("https://www.facebook.com/checkpoint/")) {
141
- if (resp.request.uri.href.includes('601051028565049')) {
142
- const fb_dtsg = utils.getFrom(resp.body, '["DTSGInitData",[],{"token":"', '","');
143
- const jazoest = utils.getFrom(resp.body, 'jazoest=', '",');
144
- const lsd = utils.getFrom(resp.body, "[\"LSD\",[],{\"token\":\"", "\"}");
145
- return utils.post("https://www.facebook.com/api/graphql/", jar, {
146
- ...FormBypass,
147
- fb_dtsg,
148
- jazoest,
149
- lsd
150
- }, globalOptions).then(utils.saveCookies(jar)).then(res => {
151
- kupal();
152
- return res;
153
- });
154
- } else return resp;
155
- } else return resp;
156
- }
157
- } catch (e) {
158
- utils.error(e);
159
- }
160
- }
161
-
162
- async function checkIfSuspended(resp, appstate) {
163
- try {
164
- const appstateCUser = (appstate.find(i => i.key == 'c_user') || appstate.find(i => i.key == 'i_user'))
165
- const UID = appstateCUser?.value;
166
- const suspendReasons = {};
167
- if (resp) {
168
- if (resp.request.uri && resp.request.uri.href.includes("https://www.facebook.com/checkpoint/")) {
169
- if (resp.request.uri.href.includes('1501092823525282')) {
170
- const daystoDisable = resp.body?.match(/"log_out_uri":"(.*?)","title":"(.*?)"/);
171
- if (daystoDisable && daystoDisable[2]) {
172
- suspendReasons.durationInfo = daystoDisable[2];
173
- utils.error(`Suspension time remaining:`, suspendReasons.durationInfo);
174
- }
175
- const reasonDescription = resp.body?.match(/"reason_section_body":"(.*?)"/);
176
- if (reasonDescription && reasonDescription[1]) {
177
- suspendReasons.longReason = reasonDescription?.[1];
178
- const reasonReplace = suspendReasons?.longReason?.toLowerCase()?.replace("your account, or activity on it, doesn't follow our community standards on ", "");
179
- suspendReasons.shortReason = reasonReplace?.substring(0, 1).toUpperCase() + reasonReplace?.substring(1);
180
- utils.error(`Alert on ${UID}:`, `Account has been suspended!`);
181
- utils.error(`Why suspended:`, suspendReasons.longReason)
182
- utils.error(`Reason on suspension:`, suspendReasons.shortReason);
183
- }
184
- ctx = null;
185
- return {
186
- suspended: true,
187
- suspendReasons
188
- }
189
- }
190
- } else return;
191
- }
192
- } catch (error) {
193
- return;
194
- }
195
- }
196
134
 
197
- async function checkIfLocked(resp, appstate) {
198
- try {
199
- const appstateCUser = (appstate.find(i => i.key == 'c_user') || appstate.find(i => i.key == 'i_user'))
200
- const UID = appstateCUser?.value;
201
- const lockedReasons = {};
202
- if (resp) {
203
- if (resp.request.uri && resp.request.uri.href.includes("https://www.facebook.com/checkpoint/")) {
204
- if (resp.request.uri.href.includes('828281030927956')) {
205
- const lockDesc = resp.body.match(/"is_unvetted_flow":true,"title":"(.*?)"/);
206
- if (lockDesc && lockDesc[1]) {
207
- lockedReasons.reason = lockDesc[1];
208
- utils.error(`Alert on ${UID}:`, lockedReasons.reason);
209
- }
210
- ctx = null;
211
- return {
212
- locked: true,
213
- lockedReasons
214
- }
215
- }
216
- } else return;
217
- }
135
+ if (resp && resp.request.uri && resp.request.uri.href.includes("https://www.facebook.com/checkpoint/")) {
136
+ if (resp.request.uri.href.includes('601051028565049')) {
137
+ const fb_dtsg = utils.getFrom(resp.body, '["DTSGInitData",[],{"token":"', '","');
138
+ const jazoest = utils.getFrom(resp.body, 'jazoest=', '",');
139
+ const lsd = utils.getFrom(resp.body, "[\"LSD\",[],{\"token\":\"", "\"}");
140
+ return utils.post("https://www.facebook.com/api/graphql/", jar, {
141
+ ...FormBypass, fb_dtsg, jazoest, lsd
142
+ }, globalOptions).then(utils.saveCookies(jar)).then(res => { kupal(); return res; });
143
+ } else return resp;
144
+ } else return resp;
218
145
  } catch (e) {
219
- utils.error("error", e);
146
+ console.error("[ AMINUL-FCA ] bypassAutoBehavior error:", e);
220
147
  }
221
148
  }
222
149
 
223
- function buildAPI(html, jar) {
224
- let fb_dtsg;
225
- let userID;
226
- const tokenMatch = html.match(/DTSGInitialData.*?token":"(.*?)"/);
227
- if (tokenMatch) {
228
- fb_dtsg = tokenMatch[1];
229
- }
230
- //hajime pogi
231
- //@Kenneth Panio: i fixed the cookie do not change or remove this line what it does? we know that facebook account allow multiple profile in single account so it allow us to login which specific profile we use
232
- let cookie = jar.getCookies("https://www.facebook.com");
233
- let primary_profile = cookie.filter(function(val) {
234
- return val.cookieString().split("=")[0] === "c_user";
235
- });
236
- let secondary_profile = cookie.filter(function(val) {
237
- return val.cookieString().split("=")[0] === "i_user";
238
- });
239
- if (primary_profile.length === 0 && secondary_profile.length === 0) {
240
- throw {
241
- error: errorRetrieving,
242
- };
243
- } else {
244
- if (html.indexOf("/checkpoint/block/?next") > -1) {
245
- return utils.warn(
246
- "login",
247
- "Checkpoint detected. Please log in with a browser to verify."
248
- );
249
- }
250
- if (secondary_profile[0] && secondary_profile[0].cookieString().includes('i_user')) {
251
- userID = secondary_profile[0].cookieString().split("=")[1].toString();
252
- } else {
253
- userID = primary_profile[0].cookieString().split("=")[1].toString();
254
- }
255
- }
256
- utils.log("Logged in!");
257
- const clientID = (Math.random() * 2147483648 | 0).toString(16);
258
- const CHECK_MQTT = {
259
- oldFBMQTTMatch: html.match(/irisSeqID:"(.+?)",appID:219994525426954,endpoint:"(.+?)"/),
260
- newFBMQTTMatch: html.match(/{"app_id":"219994525426954","endpoint":"(.+?)","iris_seq_id":"(.+?)"}/),
261
- legacyFBMQTTMatch: html.match(/\["MqttWebConfig",\[\],{"fbid":"(.*?)","appID":219994525426954,"endpoint":"(.*?)","pollingEndpoint":"(.*?)"/)
262
- }
263
- let Slot = Object.keys(CHECK_MQTT);
264
- let mqttEndpoint, irisSeqID;
265
- Object.keys(CHECK_MQTT).map((MQTT) => {
266
- if (globalOptions.bypassRegion) return;
267
- if (CHECK_MQTT[MQTT] && !region) {
268
- switch (Slot.indexOf(MQTT)) {
269
- case 0: {
270
- irisSeqID = CHECK_MQTT[MQTT][1];
271
- mqttEndpoint = CHECK_MQTT[MQTT][2].replace(/\\\//g, "/");
272
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
273
- break;
274
- }
275
- case 1: {
276
- irisSeqID = CHECK_MQTT[MQTT][2];
277
- mqttEndpoint = CHECK_MQTT[MQTT][1].replace(/\\\//g, "/");
278
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
279
- break;
280
- }
281
- case 2: {
282
- mqttEndpoint = CHECK_MQTT[MQTT][2].replace(/\\\//g, "/"); //this really important.
283
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
284
- break;
285
- }
286
- }
287
- return;
288
- }
289
- });
290
- if (globalOptions.bypassRegion)
291
- region = globalOptions.bypassRegion.toUpperCase();
292
- else if (!region)
293
- region = ["prn", "pnb", "vll", "hkg", "sin", "ftw", "ash"][Math.random() * 5 | 0].toUpperCase();
294
- if (globalOptions.bypassRegion || !mqttEndpoint)
295
- mqttEndpoint = "wss://edge-chat.facebook.com/chat?region=" + region;
296
- let ctx = {
297
- userID,
298
- jar,
299
- clientID,
300
- globalOptions,
301
- loggedIn: true,
302
- access_token: 'NONE',
303
- clientMutationId: 0,
304
- mqttClient: undefined,
305
- lastSeqId: irisSeqID,
306
- syncToken: undefined,
307
- mqttEndpoint,
308
- wsReqNumber: 0,
309
- wsTaskNumber: 0,
310
- reqCallbacks: {},
311
- region,
312
- firstListen: true,
313
- fb_dtsg
314
- };
315
- cron.schedule('0 0 * * *', () => {
316
- const fbDtsgData = JSON.parse(fs.readFileSync('fb_dtsg_data.json', 'utf8'));
317
- if (fbDtsgData && fbDtsgData[userID]) {
318
- const userFbDtsg = fbDtsgData[userID];
319
- api.refreshFb_dtsg(userFbDtsg)
320
- .then(() => utils.log(`Fb_dtsg refreshed successfully for user ${userID}.`))
321
- .catch((err) => utils.error(`Error during Fb_dtsg refresh for user ${userID}:`, err));
322
- } else {
323
- utils.error(`No fb_dtsg data found for user ${userID}.`);
324
- }
325
- }, {
326
- timezone: 'Asia/Manila'
327
- });
328
- let defaultFuncs = utils.makeDefaults(html, userID, ctx);
329
- return [ctx, defaultFuncs];
330
- }
331
-
150
+ // ================== LOGIN HELPER ==================
332
151
  async function loginHelper(appState, email, password, apiCustomized = {}, callback) {
333
- let mainPromise = null;
334
152
  const jar = utils.getJar();
335
- utils.log('Logging in...');
336
- if (appState) {
337
- if (utils.getType(appState) === 'Array' && appState.some(c => c.name)) {
338
- appState = appState.map(c => {
339
- c.key = c.name;
340
- delete c.name;
341
- return c;
342
- });
343
- }
344
- else if (utils.getType(appState) === 'String') {
345
- const arrayAppState = [];
346
- appState.split(';').forEach(c => {
347
- const [key, value] = c.split('=');
348
- arrayAppState.push({
349
- key: (key || "").trim(),
350
- value: (value || "").trim(),
351
- domain: ".facebook.com",
352
- path: "/",
353
- expires: new Date().getTime() + 1000 * 60 * 60 * 24 * 365
354
- });
355
- });
356
- appState = arrayAppState;
357
- }
153
+ console.log("[ AMINUL-FCA ] LOADING...");
154
+
155
+ if (!appState) return callback(new Error("Please provide appState."), null);
358
156
 
157
+ if (Array.isArray(appState)) {
359
158
  appState.map(c => {
360
- const str = c.key + "=" + c.value + "; expires=" + c.expires + "; domain=" + c.domain + "; path=" + c.path + ";";
159
+ const str = `${c.key}=${c.value}; expires=${c.expires}; domain=${c.domain}; path=${c.path};`;
361
160
  jar.setCookie(str, "http://" + c.domain);
362
161
  });
363
-
364
- mainPromise = utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true })
365
- .then(utils.saveCookies(jar));
366
- } else if (email && password) {
367
- throw { error: "Credentials method is not implemented to ws3-fca yet. " };
368
- } else {
369
- throw { error: "Please provide either appState or credentials." };
370
162
  }
371
163
 
372
164
  api = {
373
165
  setOptions: setOptions.bind(null, globalOptions),
374
- getAppState() {
375
- const appState = utils.getAppState(jar);
376
- if (!Array.isArray(appState)) return [];
377
- const uniqueAppState = appState.filter((item, index, self) => {
378
- return self.findIndex((t) => t.key === item.key) === index;
379
- });
380
- return uniqueAppState.length > 0 ? uniqueAppState : appState;
381
- }
166
+ getAppState: () => utils.getAppState(jar)
382
167
  };
383
- mainPromise = mainPromise
384
- .then(res => bypassAutoBehavior(res, jar, appState))
385
- .then(res => updateDTSG(res, appState))
386
- .then(async (res) => {
387
- const resp = await utils.get(`https://www.facebook.com/home.php`, jar, null, globalOptions);
388
- const html = resp?.body;
389
- const stuff = await buildAPI(html, jar);
390
- ctx = stuff[0];
391
- _defaultFuncs = stuff[1];
392
- api.addFunctions = (directory) => {
393
- const folder = directory.endsWith("/") ? directory : (directory + "/");
394
- fs.readdirSync(folder)
395
- .filter(v => v.endsWith('.js'))
396
- .map(v => {
397
- api[v.replace('.js', '')] = require(folder + v)(_defaultFuncs, api, ctx);
398
- });
399
- }
400
- api.addFunctions(__dirname + '/src');
401
- api.listen = api.listenMqtt;
402
- api.ws3 = {
403
- ...apiCustomized
404
- };
405
- const bi = await api.getBotInitialData();
406
- if (!bi.error) {
407
- utils.log("Hello,", bi.name);
408
- utils.log("My User ID:", bi.uid);
409
- ctx.userName = bi.name;
410
- } else {
411
- utils.warn(bi.error);
412
- utils.warn(`WARNING: Failed to fetch account info. Proceeding to log in for user ${ctx.userID}`);
413
- }
414
- utils.log("Connected to server region:", region || "UNKNOWN");
415
- return res;
416
- });
417
- if (globalOptions.pageID) {
418
- mainPromise = mainPromise
419
- .then(function() {
420
- return utils
421
- .get('https://www.facebook.com/' + ctx.globalOptions.pageID + '/messages/?section=messages&subsection=inbox', ctx.jar, null, globalOptions);
422
- })
423
- .then(function(resData) {
424
- let url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
425
- url = url.substring(0, url.length - 1);
426
- return utils
427
- .get('https://www.facebook.com' + url, ctx.jar, null, globalOptions);
168
+
169
+ try {
170
+ let res = await utils.get('https://www.facebook.com/', jar, null, globalOptions);
171
+ res = await bypassAutoBehavior(res, jar, appState);
172
+ res = await updateDTSG(res, appState);
173
+
174
+ const html = res?.body;
175
+ const [ctxObj, defaultFuncs] = await buildAPI(html, jar);
176
+ ctx = ctxObj;
177
+ _defaultFuncs = defaultFuncs;
178
+
179
+ api.addFunctions = (dir) => {
180
+ fs.readdirSync(dir).filter(v => v.endsWith('.js')).map(v => {
181
+ api[v.replace('.js', '')] = require(path.join(dir, v))(_defaultFuncs, api, ctx);
428
182
  });
429
- }
183
+ };
184
+ api.addFunctions(path.join(__dirname, 'src'));
430
185
 
431
- mainPromise
432
- .then(async (res) => {
433
- const detectLocked = await checkIfLocked(res, appState);
434
- if (detectLocked) throw detectLocked;
435
- const detectSuspension = await checkIfSuspended(res, appState);
436
- if (detectSuspension) throw detectSuspension;
437
- utils.log("Successfully logged in.");
438
- utils.log("To check updates: you may check on https://github.com/NethWs3Dev/ws3-fca");
439
- /*
440
- Hi 😄
441
- Eh ano namn kung nakita nyoto?
442
- Madaya naba ako nyan,
443
- Dahil may Ganito? 👇
444
- Diskarte rin kayo no,
445
- Wag puro panira!
446
-
447
- We appreciate your support on ws3-fca,
448
- Please don't remove these functions.
449
- @NethWs3Dev
450
- */
451
- try {
452
- const posts = [
453
- "pfbid0EV1fmWmvkuFDSoUkpVPu2dJTi2ff11AMgK2iJpLc8tbyZDryGMMXdjynmUHtmsyyl"
454
- ];
455
- const uids = [
456
- "100089002696653",
457
- "61566907376981",
458
- "100088806220727" // pasali hwhhaha
459
- ];
460
- for (const postId of posts) {
461
- await api.setPostReaction(postId, 2);
462
- }
463
- for (const uid of uids) {
464
- await api.follow(uid, true);
465
- };
466
- } catch (error) {
467
- utils.error("error on login:", error);
468
- }
469
- return callback(null, api);
470
- }).catch(e => callback(e));
186
+ console.log("[ AMINUL-FCA ] Successfully logged in:", ctx.userID);
187
+ callback(null, api);
188
+
189
+ } catch (err) {
190
+ callback(err);
191
+ }
471
192
  }
472
193
 
194
+ // ================== MAIN LOGIN ==================
473
195
  async function login(loginData, options, callback) {
474
- if (utils.getType(options) === 'Function' ||
475
- utils.getType(options) === 'AsyncFunction') {
476
- callback = options;
477
- options = {};
478
- }
196
+ if (typeof options === "function") { callback = options; options = {}; }
479
197
  const globalOptions = {
480
- selfListen: false,
481
- selfListenEvent: false,
482
- listenEvents: true,
483
- listenTyping: false,
484
- updatePresence: false,
485
- forceLogin: false,
486
- autoMarkDelivery: false,
487
- autoMarkRead: true,
488
- autoReconnect: true,
489
- online: true,
490
- emitReady: false,
491
- userAgent: utils.defaultUserAgent,
492
- randomUserAgent: false
198
+ selfListen: false, listenEvents: true, online: true, autoMarkRead: true,
199
+ autoReconnect: true, emitReady: false, updatePresence: false, randomUserAgent: false
493
200
  };
494
201
  if (options) Object.assign(globalOptions, options);
495
- const loginws3 = () => {
496
- loginHelper(loginData?.appState, loginData?.email, loginData?.password, {
497
- relogin() {
498
- loginws3();
499
- }
500
- },
501
- (loginError, loginApi) => {
502
- if (loginError) {
503
- if (isBehavior) {
504
- utils.warn("Failed after dismiss behavior, will relogin automatically...");
505
- isBehavior = false;
506
- loginws3();
507
- }
508
- utils.error("login", loginError);
509
- return callback(loginError);
510
- }
511
- callback(null, loginApi);
512
- });
513
- }
514
- setOptions(globalOptions, options).then(_ => loginws3());
515
- return;
202
+
203
+ setOptions(globalOptions, options).then(() => loginHelper(loginData?.appState, loginData?.email, loginData?.password, {}, callback));
516
204
  }
517
205
 
518
- module.exports = { login, logging };
206
+ module.exports = login;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aminul-new-fca",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "description": "A modern Facebook Chat API fork | Made & Maintained by Aminul Sardar 🦋",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/utils.js CHANGED
@@ -1,17 +1,7 @@
1
- // reprogrammed by rui
2
- // credits to original owners
3
-
4
1
  /* eslint-disable no-prototype-builtins */
5
2
  "use strict";
6
3
 
7
- const chalk = require("chalk");
8
- const gradient = require("gradient-string");
9
- const echaceb = gradient(["#0061ff", "#681297"]);
10
- const ws = echaceb("ws3-fca");
11
4
  const getRandom = arr => arr[Math.floor(Math.random() * arr.length)];
12
- const defaultUserAgent = "facebookexternalhit/1.1";
13
- const windowsUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3";
14
-
15
5
  function randomUserAgent() {
16
6
  const platform = {
17
7
  platform: ['Windows NT 10.0; Win64; x64', 'Macintosh; Intel Mac OS X 14.7; rv:132.0'],
@@ -26,7 +16,7 @@ function randomUserAgent() {
26
16
  const plat = getRandom(platform.platform);
27
17
  const userAgentArray = [
28
18
  defaultUserAgent,
29
- windowsUserAgent,
19
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
30
20
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15",
31
21
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:45.0) Gecko/20100101 Firefox/45.0",
32
22
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0",
@@ -40,13 +30,15 @@ function randomUserAgent() {
40
30
  ]);
41
31
  return ua;
42
32
  }
33
+ const defaultUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.7; rv:132.0) Gecko/20100101 Firefox/132.0";
43
34
  const headers = {
44
35
  "content-type": "application/x-www-form-urlencoded",
45
36
  "referer": "https://www.facebook.com/",
46
37
  "origin": "https://www.facebook.com",
47
38
  "connection": "keep-alive",
48
39
  "Sec-Fetch-Site": "same-origin",
49
- "Sec-Fetch-User": "?1"
40
+ "Sec-Fetch-User": "?1",
41
+ "User-Agent": defaultUserAgent
50
42
  };
51
43
  let request = require("request").defaults({
52
44
  jar: true
@@ -54,6 +46,7 @@ let request = require("request").defaults({
54
46
  const stream = require("stream");
55
47
  const querystring = require("querystring");
56
48
  const url = require("url");
49
+
57
50
  function setProxy(proxy) {
58
51
  request = require("request").defaults({
59
52
  jar: true,
@@ -67,13 +60,12 @@ function setProxy(proxy) {
67
60
  function getHeaders(url, options, ctx, customHeader) {
68
61
  const headers1 = {
69
62
  "host": new URL(url).hostname,
70
- ...headers,
71
- "User-Agent": customHeader?.customUserAgent ?? options?.userAgent ?? defaultUserAgent
63
+ ...headers
72
64
  }
73
- /*if (headers1["User-Agent"]) {
65
+ if (headers1["User-Agent"]) {
74
66
  delete headers1["User-Agent"];
75
67
  headers1["User-Agent"] = customHeader?.customUserAgent ?? options?.userAgent ?? defaultUserAgent;
76
- */
68
+ }
77
69
  if (ctx && ctx.region) headers1["X-MSGR-Region"] = ctx.region;
78
70
  if (customHeader) {
79
71
  Object.assign(headers1, customHeader);
@@ -87,32 +79,23 @@ function isReadableStream(obj) {
87
79
  return obj instanceof stream.Stream && typeof obj._read == "function" && getType(obj._readableState) == "Object";
88
80
  }
89
81
 
90
- function cleanGet(url) {
91
- let callback;
92
- var returnPromise = new Promise(function(resolve, reject) {
93
- callback = (error, res) => error ? reject(error) : resolve(res);
94
- });
95
- request.get(url, { timeout: 60000 }, callback);
96
- return returnPromise;
97
- }
98
-
99
82
  function get(url, jar, qs, options, ctx, customHeader) {
100
- let callback;
83
+ let callback;
101
84
  var returnPromise = new Promise(function (resolve, reject) {
102
85
  callback = (error, res) => error ? reject(error) : resolve(res);
103
86
  });
104
- if (getType(qs) == "Object")
87
+ if (getType(qs) == "Object")
105
88
  for (let prop in qs) {
106
89
  if (getType(qs[prop]) == 'Object')
107
90
  qs[prop] = JSON.stringify(qs[prop]);
108
91
  }
109
- var op = {
92
+ var op = {
110
93
  headers: getHeaders(url, options, ctx, customHeader),
111
- timeout: 60000,
112
- qs,
113
- jar,
114
- gzip: true
115
- }
94
+ timeout: 60000,
95
+ qs,
96
+ jar,
97
+ gzip: true
98
+ }
116
99
 
117
100
  request.get(url, op, callback);
118
101
 
@@ -124,18 +107,18 @@ function post(url, jar, form, options, ctx, customHeader) {
124
107
  var returnPromise = new Promise(function (resolve, reject) {
125
108
  callback = (error, res) => error ? reject(error) : resolve(res);
126
109
  });
127
-
128
- var op = {
110
+
111
+ var op = {
129
112
  headers: getHeaders(url, options, ctx, customHeader),
130
113
  timeout: 60000,
131
- form,
132
- jar,
133
- gzip: true
134
- }
114
+ form,
115
+ jar,
116
+ gzip: true
117
+ }
135
118
 
136
119
  request.post(url, op, callback);
137
120
 
138
- return returnPromise;
121
+ return returnPromise;
139
122
  }
140
123
 
141
124
  function postFormData(url, jar, form, qs, options, ctx) {
@@ -148,20 +131,20 @@ function postFormData(url, jar, form, qs, options, ctx) {
148
131
  if (getType(qs[prop]) == 'Object')
149
132
  qs[prop] = JSON.stringify(qs[prop]);
150
133
  }
151
- var op = {
152
- headers: getHeaders(url, options, ctx, {
134
+ var op = {
135
+ headers: getHeaders(url, options, ctx, {
153
136
  'content-type': 'multipart/form-data'
154
137
  }),
155
- timeout: 60000,
156
- formData: form,
157
- qs,
158
- jar,
159
- gzip: true
160
- }
138
+ timeout: 60000,
139
+ formData: form,
140
+ qs,
141
+ jar,
142
+ gzip: true
143
+ }
161
144
 
162
145
  request.post(url, op, callback);
163
146
 
164
- return returnPromise;
147
+ return returnPromise;
165
148
  }
166
149
 
167
150
 
@@ -289,7 +272,7 @@ function generatePresence(userID) {
289
272
  at: time
290
273
  },
291
274
  ch: {
292
- ["p_" + userID]: 0
275
+ ["p_" + userID]: 0
293
276
  }
294
277
  })
295
278
  )
@@ -1248,18 +1231,18 @@ function saveCookies(jar) {
1248
1231
  }
1249
1232
 
1250
1233
  const NUM_TO_MONTH = [
1251
- "Jan",
1252
- "Feb",
1253
- "Mar",
1254
- "Apr",
1255
- "May",
1256
- "Jun",
1257
- "Jul",
1258
- "Aug",
1259
- "Sep",
1260
- "Oct",
1261
- "Nov",
1262
- "Dec"
1234
+ "Jan",
1235
+ "Feb",
1236
+ "Mar",
1237
+ "Apr",
1238
+ "May",
1239
+ "Jun",
1240
+ "Jul",
1241
+ "Aug",
1242
+ "Sep",
1243
+ "Oct",
1244
+ "Nov",
1245
+ "Dec"
1263
1246
  ];
1264
1247
  const NUM_TO_DAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
1265
1248
 
@@ -1382,29 +1365,10 @@ function getAccessFromBusiness(jar, Options) {
1382
1365
  }
1383
1366
  }
1384
1367
 
1385
- let logging = true;
1386
-
1387
1368
  const meta = prop => new RegExp(`<meta property="${prop}" content="([^"]*)"`);
1369
+
1388
1370
  module.exports = {
1389
- //logs
1390
- log(...args) {
1391
- if (!logging) return;
1392
- console.log(ws, chalk.green.bold("[LOG]"), ...args);
1393
- },
1394
- error(...args) {
1395
- if (!logging) return;
1396
- console.error(ws, chalk.red.bold("[ERROR]"), ...args);
1397
- },
1398
- warn(...args) {
1399
- if (!logging) return;
1400
- console.warn(ws, chalk.yellow.bold("[WARNING]"), ...args);
1401
- },
1402
- setLogging(bool) {
1403
- logging = Boolean(bool);
1404
- },
1405
- //end logs
1406
1371
  isReadableStream,
1407
- cleanGet,
1408
1372
  get,
1409
1373
  post,
1410
1374
  postFormData,
@@ -1447,7 +1411,6 @@ module.exports = {
1447
1411
  presenceEncode,
1448
1412
  headers,
1449
1413
  defaultUserAgent,
1450
- windowsUserAgent,
1451
1414
  randomUserAgent,
1452
1415
  meta
1453
1416
  };