rapido-fca 0.0.1 → 0.0.2

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 (81) hide show
  1. package/index.js +415 -419
  2. package/package.json +1 -1
  3. package/readme.md +39 -237
  4. package/src/addExternalModule.js +23 -19
  5. package/src/addUserToGroup.js +97 -99
  6. package/src/changeAdminStatus.js +62 -86
  7. package/src/changeArchivedStatus.js +49 -49
  8. package/src/changeAvatar.js +108 -118
  9. package/src/changeBio.js +64 -63
  10. package/src/changeBlockedStatus.js +38 -40
  11. package/src/changeGroupImage.js +126 -129
  12. package/src/changeNickname.js +49 -49
  13. package/src/changeThreadColor.js +53 -53
  14. package/src/changeThreadEmoji.js +45 -45
  15. package/src/createNewGroup.js +72 -74
  16. package/src/createPoll.js +59 -59
  17. package/src/deleteMessage.js +50 -50
  18. package/src/deleteThread.js +50 -50
  19. package/src/editMessage.js +49 -51
  20. package/src/forwardAttachment.js +54 -54
  21. package/src/getCurrentUserID.js +3 -3
  22. package/src/getEmojiUrl.js +17 -17
  23. package/src/getFriendsList.js +67 -67
  24. package/src/getMessage.js +767 -806
  25. package/src/getThreadHistory.js +642 -656
  26. package/src/getThreadInfo.js +1 -1
  27. package/src/getThreadList.js +227 -199
  28. package/src/getThreadPictures.js +71 -51
  29. package/src/getUserID.js +58 -53
  30. package/src/getUserInfo.js +60 -52
  31. package/src/handleFriendRequest.js +65 -41
  32. package/src/handleMessageRequest.js +60 -42
  33. package/src/httpGet.js +57 -49
  34. package/src/httpPost.js +57 -48
  35. package/src/httpPostFormData.js +63 -0
  36. package/src/listenMqtt.js +895 -827
  37. package/src/logout.js +61 -61
  38. package/src/markAsDelivered.js +53 -42
  39. package/src/markAsRead.js +69 -59
  40. package/src/markAsReadAll.js +42 -32
  41. package/src/markAsSeen.js +54 -43
  42. package/src/muteThread.js +47 -40
  43. package/src/refreshFb_dtsg.js +69 -77
  44. package/src/removeUserFromGroup.js +67 -67
  45. package/src/resolvePhotoUrl.js +34 -34
  46. package/src/searchForThread.js +43 -43
  47. package/src/sendMessage.js +228 -80
  48. package/src/sendTypingIndicator.js +88 -86
  49. package/src/setMessageReaction.js +109 -110
  50. package/src/setPostReaction.js +87 -90
  51. package/src/setTitle.js +72 -76
  52. package/src/threadColors.js +121 -121
  53. package/src/unfriend.js +43 -43
  54. package/src/unsendMessage.js +38 -34
  55. package/src/uploadAttachment.js +81 -79
  56. package/utils.js +1401 -2732
  57. package/src/changeAvatarV2.js +0 -86
  58. package/src/changeAvt.js +0 -85
  59. package/src/changeBlockedStatusMqtt.js +0 -80
  60. package/src/changeCover.js +0 -72
  61. package/src/changeName.js +0 -79
  62. package/src/changeUsername.js +0 -59
  63. package/src/createCommentPost.js +0 -230
  64. package/src/createPost.js +0 -276
  65. package/src/editMessageOld.js +0 -67
  66. package/src/follow.js +0 -74
  67. package/src/getAccess.js +0 -112
  68. package/src/getAvatarUser.js +0 -78
  69. package/src/getRegion.js +0 -7
  70. package/src/getThreadHistoryDeprecated.js +0 -71
  71. package/src/getThreadInfoDeprecated.js +0 -56
  72. package/src/getThreadListDeprecated.js +0 -46
  73. package/src/getUID.js +0 -119
  74. package/src/searchStickers.js +0 -53
  75. package/src/sendMessageMqtt.js +0 -322
  76. package/src/sendTypingIndicatorV2.js +0 -28
  77. package/src/setMessageReactionMqtt.js +0 -62
  78. package/src/setStoryReaction.js +0 -64
  79. package/src/shareContact.js +0 -110
  80. package/src/shareLink.js +0 -59
  81. package/src/stopListenMqtt.js +0 -23
package/index.js CHANGED
@@ -3,458 +3,454 @@
3
3
  var utils = require("./utils");
4
4
  var cheerio = require("cheerio");
5
5
  var log = require("npmlog");
6
- /*var { getThemeColors } = require("../../func/utils/log.js");
7
- var logger = require("../../func/utils/log.js");
8
- var { cra, cv, cb, co } = getThemeColors();*/
9
6
  log.maxRecordSize = 100;
10
7
  var checkVerified = null;
11
8
  const Boolean_Option = ['online', 'selfListen', 'listenEvents', 'updatePresence', 'forceLogin', 'autoMarkDelivery', 'autoMarkRead', 'listenTyping', 'autoReconnect', 'emitReady'];
12
9
  global.ditconmemay = false;
13
10
 
14
11
  function setOptions(globalOptions, options) {
15
- Object.keys(options).map(function (key) {
16
- switch (Boolean_Option.includes(key)) {
17
- case true: {
18
- globalOptions[key] = Boolean(options[key]);
19
- break;
20
- }
21
- case false: {
22
- switch (key) {
23
- case 'pauseLog': {
24
- if (options.pauseLog) log.pause();
25
- else log.resume();
26
- break;
27
- }
28
- case 'logLevel': {
29
- log.level = options.logLevel;
30
- globalOptions.logLevel = options.logLevel;
31
- break;
32
- }
33
- case 'logRecordSize': {
34
- log.maxRecordSize = options.logRecordSize;
35
- globalOptions.logRecordSize = options.logRecordSize;
36
- break;
37
- }
38
- case 'pageID': {
39
- globalOptions.pageID = options.pageID.toString();
40
- break;
41
- }
42
- case 'userAgent': {
43
- 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');
44
- break;
45
- }
46
- case 'proxy': {
47
- if (typeof options.proxy != "string") {
48
- delete globalOptions.proxy;
49
- utils.setProxy();
50
- } else {
51
- globalOptions.proxy = options.proxy;
52
- utils.setProxy(globalOptions.proxy);
53
- }
54
- break;
55
- }
56
- default: {
57
- log.warn("setOptions", "Unrecognized option given to setOptions: " + key);
58
- break;
59
- }
60
- }
61
- break;
62
- }
63
- }
64
- });
12
+ Object.keys(options).map(function (key) {
13
+ switch (Boolean_Option.includes(key)) {
14
+ case true: {
15
+ globalOptions[key] = Boolean(options[key]);
16
+ break;
17
+ }
18
+ case false: {
19
+ switch (key) {
20
+ case 'pauseLog': {
21
+ if (options.pauseLog) log.pause();
22
+ else log.resume();
23
+ break;
24
+ }
25
+ case 'logLevel': {
26
+ log.level = options.logLevel;
27
+ globalOptions.logLevel = options.logLevel;
28
+ break;
29
+ }
30
+ case 'logRecordSize': {
31
+ log.maxRecordSize = options.logRecordSize;
32
+ globalOptions.logRecordSize = options.logRecordSize;
33
+ break;
34
+ }
35
+ case 'pageID': {
36
+ globalOptions.pageID = options.pageID.toString();
37
+ break;
38
+ }
39
+ case 'userAgent': {
40
+ 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');
41
+ break;
42
+ }
43
+ case 'proxy': {
44
+ if (typeof options.proxy != "string") {
45
+ delete globalOptions.proxy;
46
+ utils.setProxy();
47
+ } else {
48
+ globalOptions.proxy = options.proxy;
49
+ utils.setProxy(globalOptions.proxy);
50
+ }
51
+ break;
52
+ }
53
+ default: {
54
+ log.warn("setOptions", "Unrecognized option given to setOptions: " + key);
55
+ break;
56
+ }
57
+ }
58
+ break;
59
+ }
60
+ }
61
+ });
65
62
  }
66
63
 
67
64
  function buildAPI(globalOptions, html, jar) {
68
- let fb_dtsg = null;
69
- let irisSeqID = null;
70
- function extractFromHTML() {
71
- try {
72
- const $ = cheerio.load(html);
73
- $('script').each((i, script) => {
74
- if (!fb_dtsg) {
75
- const scriptText = $(script).html() || '';
76
- const patterns = [
77
- /\["DTSGInitialData",\[\],{"token":"([^"]+)"}]/,
78
- /\["DTSGInitData",\[\],{"token":"([^"]+)"/,
79
- /"token":"([^"]+)"/,
80
- /{\\"token\\":\\"([^\\]+)\\"/,
81
- /,\{"token":"([^"]+)"\},\d+\]/,
82
- /"async_get_token":"([^"]+)"/,
83
- /"dtsg":\{"token":"([^"]+)"/,
84
- /DTSGInitialData[^>]+>([^<]+)/
85
- ];
86
- for (const pattern of patterns) {
87
- const match = scriptText.match(pattern);
88
- if (match && match[1]) {
89
- try {
90
- const possibleJson = match[1].replace(/\\"/g, '"');
91
- const parsed = JSON.parse(possibleJson);
92
- fb_dtsg = parsed.token || parsed;
93
- } catch {
94
- fb_dtsg = match[1];
95
- }
96
- if (fb_dtsg) break;
97
- }
98
- }
99
- }
100
- });
101
- if (!fb_dtsg) {
102
- const dtsgInput = $('input[name="fb_dtsg"]').val();
103
- if (dtsgInput) fb_dtsg = dtsgInput;
104
- }
105
- const seqMatches = html.match(/irisSeqID":"([^"]+)"/);
106
- if (seqMatches && seqMatches[1]) {
107
- irisSeqID = seqMatches[1];
108
- }
109
- try {
110
- const jsonMatches = html.match(/\{"dtsg":({[^}]+})/);
111
- if (jsonMatches && jsonMatches[1]) {
112
- const dtsgData = JSON.parse(jsonMatches[1]);
113
- if (dtsgData.token) fb_dtsg = dtsgData.token;
114
- }
115
- } catch { }
116
- if (fb_dtsg) {
117
- console.log("Found fb_dtsg!");
118
- }
119
- } catch (e) {
120
- console.log("Error finding fb_dtsg:", e);
121
- }
122
- }
123
- extractFromHTML();
124
- var userID;
125
- var cookies = jar.getCookies("https://www.facebook.com");
126
- var userCookie = cookies.find(cookie => cookie.cookieString().startsWith("c_user="));
127
- var tiktikCookie = cookies.find(cookie => cookie.cookieString().startsWith("i_user="));
128
- if (!userCookie && !tiktikCookie) {
129
- return log.error("Error! Your cookiestate is not valid!");
130
- }
131
- if (html.includes("/checkpoint/block/?next")) {
132
- return log.error('error', "Appstate is dead rechange it!", 'error');
133
- }
134
- userID = (tiktikCookie || userCookie).cookieString().split("=")[1];
135
- //logger.log(`${cra(`[ CONNECT ]`)} Logged in as ${userID}`, "DATABASE");
136
- try { clearInterval(checkVerified); } catch (_) { }
137
- const clientID = (Math.random() * 2147483648 | 0).toString(16);
138
- let mqttEndpoint = `wss://edge-chat.facebook.com/chat?region=prn&sid=${userID}`;
139
- let region = "PRN";
65
+ let fb_dtsg = null;
66
+ let irisSeqID = null;
67
+ function extractFromHTML() {
68
+ try {
69
+ const $ = cheerio.load(html);
70
+ $('script').each((i, script) => {
71
+ if (!fb_dtsg) {
72
+ const scriptText = $(script).html() || '';
73
+ const patterns = [
74
+ /\["DTSGInitialData",\[\],{"token":"([^"]+)"}]/,
75
+ /\["DTSGInitData",\[\],{"token":"([^"]+)"/,
76
+ /"token":"([^"]+)"/,
77
+ /{\\"token\\":\\"([^\\]+)\\"/,
78
+ /,\{"token":"([^"]+)"\},\d+\]/,
79
+ /"async_get_token":"([^"]+)"/,
80
+ /"dtsg":\{"token":"([^"]+)"/,
81
+ /DTSGInitialData[^>]+>([^<]+)/
82
+ ];
83
+ for (const pattern of patterns) {
84
+ const match = scriptText.match(pattern);
85
+ if (match && match[1]) {
86
+ try {
87
+ const possibleJson = match[1].replace(/\\"/g, '"');
88
+ const parsed = JSON.parse(possibleJson);
89
+ fb_dtsg = parsed.token || parsed;
90
+ } catch {
91
+ fb_dtsg = match[1];
92
+ }
93
+ if (fb_dtsg) break;
94
+ }
95
+ }
96
+ }
97
+ });
98
+ if (!fb_dtsg) {
99
+ const dtsgInput = $('input[name="fb_dtsg"]').val();
100
+ if (dtsgInput) fb_dtsg = dtsgInput;
101
+ }
102
+ const seqMatches = html.match(/irisSeqID":"([^"]+)"/);
103
+ if (seqMatches && seqMatches[1]) {
104
+ irisSeqID = seqMatches[1];
105
+ }
106
+ try {
107
+ const jsonMatches = html.match(/\{"dtsg":({[^}]+})/);
108
+ if (jsonMatches && jsonMatches[1]) {
109
+ const dtsgData = JSON.parse(jsonMatches[1]);
110
+ if (dtsgData.token) fb_dtsg = dtsgData.token;
111
+ }
112
+ } catch { }
113
+ if (fb_dtsg) {
114
+ log.info("✅ | Found fb_Dtsg");
115
+ }
116
+ } catch (e) {
117
+ console.log("Error finding fb_dtsg:", e);
118
+ }
119
+ }
120
+ extractFromHTML();
121
+ var userID;
122
+ var cookies = jar.getCookies("https://www.facebook.com");
123
+ var userCookie = cookies.find(cookie => cookie.cookieString().startsWith("c_user="));
124
+ var tiktikCookie = cookies.find(cookie => cookie.cookieString().startsWith("i_user="));
125
+ if (!userCookie && !tiktikCookie) {
126
+ return log.error('login', "No cookie found for user, please check login information again");
127
+ }
128
+ if (html.includes("/checkpoint/block/?next")) {
129
+ return log.error('login', "Appstate dead, please replace with a new one!", 'error');
130
+ }
131
+ userID = (tiktikCookie || userCookie).cookieString().split("=")[1];
132
+
133
+ try { clearInterval(checkVerified); } catch (_) { }
134
+ const clientID = (Math.random() * 2147483648 | 0).toString(16);
135
+ let mqttEndpoint = `wss://edge-chat.facebook.com/chat?region=prn&sid=${userID}`;
136
+ let region = "PRN";
140
137
 
141
- try {
142
- const endpointMatch = html.match(/"endpoint":"([^"]+)"/);
143
- if (endpointMatch.input.includes("601051028565049")) {
144
- console.log(`login error.`);
145
- ditconmemay = true;
146
- }
147
- if (endpointMatch) {
148
- mqttEndpoint = endpointMatch[1].replace(/\\\//g, '/');
149
- const url = new URL(mqttEndpoint);
150
- region = url.searchParams.get('region')?.toUpperCase() || "PRN";
151
- }
152
- } catch (e) {
153
- console.log('Using default MQTT endpoint');
154
- }
155
- log.info('Logging in...');
156
- var ctx = {
157
- userID: userID,
158
- jar: jar,
159
- clientID: clientID,
160
- globalOptions: globalOptions,
161
- loggedIn: true,
162
- access_token: 'NONE',
163
- clientMutationId: 0,
164
- mqttClient: undefined,
165
- lastSeqId: irisSeqID,
166
- syncToken: undefined,
167
- mqttEndpoint: mqttEndpoint,
168
- region: region,
169
- firstListen: true,
170
- fb_dtsg: fb_dtsg,
171
- req_ID: 0,
172
- callback_Task: {},
173
- wsReqNumber: 0,
174
- wsTaskNumber: 0,
175
- reqCallbacks: {}
176
- };
177
- var api = {
178
- setOptions: setOptions.bind(null, globalOptions),
179
- getAppState: () => utils.getAppState(jar),
180
- postFormData: (url, body) => utils.makeDefaults(html, userID, ctx).postFormData(url, ctx.jar, body)
181
- };
182
- var defaultFuncs = utils.makeDefaults(html, userID, ctx);
183
- api.postFormData = function (url, body) {
184
- return defaultFuncs.postFormData(url, ctx.jar, body);
185
- };
186
- api.getFreshDtsg = async function () {
187
- try {
188
- const res = await defaultFuncs.get('https://www.facebook.com/', jar, null, globalOptions);
189
- const $ = cheerio.load(res.body);
190
- let newDtsg;
191
- const patterns = [
192
- /\["DTSGInitialData",\[\],{"token":"([^"]+)"}]/,
193
- /\["DTSGInitData",\[\],{"token":"([^"]+)"/,
194
- /"token":"([^"]+)"/,
195
- /name="fb_dtsg" value="([^"]+)"/
196
- ];
138
+ try {
139
+ const endpointMatch = html.match(/"endpoint":"([^"]+)"/);
140
+ if (endpointMatch.input.includes("601051028565049")) {
141
+ console.log(`login error due to automatic account`);
142
+ ditconmemay = true;
143
+ }
144
+ if (endpointMatch) {
145
+ mqttEndpoint = endpointMatch[1].replace(/\\\//g, '/');
146
+ const url = new URL(mqttEndpoint);
147
+ region = url.searchParams.get('region')?.toUpperCase() || "PRN";
148
+ }
149
+ } catch (e) {
150
+ console.log('Using default MQTT endpoint');
151
+ }
152
+ var ctx = {
153
+ userID: userID,
154
+ jar: jar,
155
+ clientID: clientID,
156
+ globalOptions: globalOptions,
157
+ loggedIn: true,
158
+ access_token: 'NONE',
159
+ clientMutationId: 0,
160
+ mqttClient: undefined,
161
+ lastSeqId: irisSeqID,
162
+ syncToken: undefined,
163
+ mqttEndpoint: mqttEndpoint,
164
+ region: region,
165
+ firstListen: true,
166
+ fb_dtsg: fb_dtsg,
167
+ req_ID: 0,
168
+ callback_Task: {},
169
+ wsReqNumber: 0,
170
+ wsTaskNumber: 0,
171
+ reqCallbacks: {}
172
+ };
173
+ var api = {
174
+ setOptions: setOptions.bind(null, globalOptions),
175
+ getAppState: () => utils.getAppState(jar),
176
+ postFormData: (url, body) => utils.makeDefaults(html, userID, ctx).postFormData(url, ctx.jar, body)
177
+ };
178
+ var defaultFuncs = utils.makeDefaults(html, userID, ctx);
179
+ api.postFormData = function (url, body) {
180
+ return defaultFuncs.postFormData(url, ctx.jar, body);
181
+ };
182
+ api.getFreshDtsg = async function () {
183
+ try {
184
+ const res = await defaultFuncs.get('https://www.facebook.com/', jar, null, globalOptions);
185
+ const $ = cheerio.load(res.body);
186
+ let newDtsg;
187
+ const patterns = [
188
+ /\["DTSGInitialData",\[\],{"token":"([^"]+)"}]/,
189
+ /\["DTSGInitData",\[\],{"token":"([^"]+)"/,
190
+ /"token":"([^"]+)"/,
191
+ /name="fb_dtsg" value="([^"]+)"/
192
+ ];
197
193
 
198
- $('script').each((i, script) => {
199
- if (!newDtsg) {
200
- const scriptText = $(script).html() || '';
201
- for (const pattern of patterns) {
202
- const match = scriptText.match(pattern);
203
- if (match && match[1]) {
204
- newDtsg = match[1];
205
- break;
206
- }
207
- }
208
- }
209
- });
194
+ $('script').each((i, script) => {
195
+ if (!newDtsg) {
196
+ const scriptText = $(script).html() || '';
197
+ for (const pattern of patterns) {
198
+ const match = scriptText.match(pattern);
199
+ if (match && match[1]) {
200
+ newDtsg = match[1];
201
+ break;
202
+ }
203
+ }
204
+ }
205
+ });
210
206
 
211
- if (!newDtsg) {
212
- newDtsg = $('input[name="fb_dtsg"]').val();
213
- }
207
+ if (!newDtsg) {
208
+ newDtsg = $('input[name="fb_dtsg"]').val();
209
+ }
214
210
 
215
- return newDtsg;
216
- } catch (e) {
217
- console.log("Error getting fresh dtsg:", e);
218
- return null;
219
- }
220
- };
221
- //if (noMqttData) api.htmlData = noMqttData;
222
- require('fs').readdirSync(__dirname + '/src/').filter(v => v.endsWith('.js')).forEach(v => { api[v.replace('.js', '')] = require(`./src/${v}`)(utils.makeDefaults(html, userID, ctx), api, ctx); });
223
- api.listen = api.listenMqtt;
224
- return {
225
- ctx,
226
- defaultFuncs,
227
- api
228
- };
211
+ return newDtsg;
212
+ } catch (e) {
213
+ console.log("Error getting fresh dtsg:", e);
214
+ return null;
215
+ }
216
+ };
217
+
218
+ require('fs').readdirSync(__dirname + '/src/').filter(v => v.endsWith('.js')).forEach(v => { api[v.replace('.js', '')] = require(`./src/${v}`)(utils.makeDefaults(html, userID, ctx), api, ctx); });
219
+ api.listen = api.listenMqtt;
220
+ return {
221
+ ctx,
222
+ defaultFuncs,
223
+ api
224
+ };
229
225
  }
230
226
 
231
227
  function makeLogin(jar, email, password, loginOptions, callback, prCallback) {
232
- return async function (res) {
233
- try {
234
- const html = res.body;
235
- const $ = cheerio.load(html);
236
- let arr = [];
237
- $("#login_form input").each((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
238
- arr = arr.filter(v => v.val && v.val.length);
239
- let form = utils.arrToForm(arr);
240
- form.lsd = utils.getFrom(html, "[\"LSD\",[],{\"token\":\"", "\"}");
241
- form.lgndim = Buffer.from(JSON.stringify({ w: 1440, h: 900, aw: 1440, ah: 834, c: 24 })).toString('base64');
242
- form.email = email;
243
- form.pass = password;
244
- form.default_persistent = '0';
245
- form.lgnrnd = utils.getFrom(html, "name=\"lgnrnd\" value=\"", "\"");
246
- form.locale = 'en_US';
247
- form.timezone = '240';
248
- form.lgnjs = Math.floor(Date.now() / 1000);
249
- const willBeCookies = html.split("\"_js_");
250
- willBeCookies.slice(1).forEach(val => {
251
- const cookieData = JSON.parse("[\"" + utils.getFrom(val, "", "]") + "]");
252
- jar.setCookie(utils.formatCookie(cookieData, "facebook"), "https://www.facebook.com");
253
- });
254
- log.info("Logging in...");
255
- const loginRes = await utils.post(
256
- "https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110",
257
- jar,
258
- form,
259
- loginOptions
260
- );
261
- await utils.saveCookies(jar)(loginRes);
262
- const headers = loginRes.headers;
263
- if (!headers.location) throw new Error("Wrong username/password.");
264
- if (headers.location.includes('https://www.facebook.com/checkpoint/')) {
265
- log.info("login", "You have login approvals turned on.");
266
- const checkpointRes = await utils.get(headers.location, jar, null, loginOptions);
267
- await utils.saveCookies(jar)(checkpointRes);
268
- const checkpointHtml = checkpointRes.body;
269
- const $ = cheerio.load(checkpointHtml);
270
- let checkpointForm = [];
271
- $("form input").each((i, v) => checkpointForm.push({ val: $(v).val(), name: $(v).attr("name") }));
272
- checkpointForm = checkpointForm.filter(v => v.val && v.val.length);
273
- const form = utils.arrToForm(checkpointForm);
274
- if (checkpointHtml.includes("checkpoint/?next")) {
275
- return new Promise((resolve, reject) => {
276
- const submit2FA = async (code) => {
277
- try {
278
- form.approvals_code = code;
279
- form['submit[Continue]'] = $("#checkpointSubmitButton").html();
280
- const approvalRes = await utils.post(
281
- "https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php",
282
- jar,
283
- form,
284
- loginOptions
285
- );
286
- await utils.saveCookies(jar)(approvalRes);
287
- const approvalError = $("#approvals_code").parent().attr("data-xui-error");
288
- if (approvalError) throw new Error("Invalid 2FA code.");
289
- form.name_action_selected = 'dont_save';
290
- const finalRes = await utils.post(
291
- "https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php",
292
- jar,
293
- form,
294
- loginOptions
295
- );
296
- await utils.saveCookies(jar)(finalRes);
297
- const appState = utils.getAppState(jar);
298
- resolve(await loginHelper(appState, email, password, loginOptions, callback));
299
- } catch (error) {
300
- reject(error);
301
- }
302
- };
303
- throw {
304
- error: 'login-approval',
305
- continue: submit2FA
306
- };
307
- });
308
- }
309
- if (!loginOptions.forceLogin) throw new Error("Couldn't login. Facebook might have blocked this account.");
310
- form['submit[This was me]'] = checkpointHtml.includes("Suspicious Login Attempt") ? "This was me" : "This Is Okay";
311
- await utils.post("https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php", jar, form, loginOptions);
312
- form.name_action_selected = 'save_device';
313
- const reviewRes = await utils.post("https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php", jar, form, loginOptions);
314
- const appState = utils.getAppState(jar);
315
- return await loginHelper(appState, email, password, loginOptions, callback);
316
- }
317
- await utils.get('https://www.facebook.com/', jar, null, loginOptions);
318
- return await utils.saveCookies(jar);
319
- } catch (error) {
320
- callback(error);
321
- }
322
- };
228
+ return async function (res) {
229
+ try {
230
+ const html = res.body;
231
+ const $ = cheerio.load(html);
232
+ let arr = [];
233
+ $("#login_form input").each((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
234
+ arr = arr.filter(v => v.val && v.val.length);
235
+ let form = utils.arrToForm(arr);
236
+ form.lsd = utils.getFrom(html, "[\"LSD\",[],{\"token\":\"", "\"}");
237
+ form.lgndim = Buffer.from(JSON.stringify({ w: 1440, h: 900, aw: 1440, ah: 834, c: 24 })).toString('base64');
238
+ form.email = email;
239
+ form.pass = password;
240
+ form.default_persistent = '0';
241
+ form.lgnrnd = utils.getFrom(html, "name=\"lgnrnd\" value=\"", "\"");
242
+ form.locale = 'en_US';
243
+ form.timezone = '240';
244
+ form.lgnjs = Math.floor(Date.now() / 1000);
245
+ const willBeCookies = html.split("\"_js_");
246
+ willBeCookies.slice(1).forEach(val => {
247
+ const cookieData = JSON.parse("[\"" + utils.getFrom(val, "", "]") + "]");
248
+ jar.setCookie(utils.formatCookie(cookieData, "facebook"), "https://www.facebook.com");
249
+ });
250
+ log.info("login", "Logging in...");
251
+ const loginRes = await utils.post(
252
+ "https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110",
253
+ jar,
254
+ form,
255
+ loginOptions
256
+ );
257
+ await utils.saveCookies(jar)(loginRes);
258
+ const headers = loginRes.headers;
259
+ if (!headers.location) throw new Error("Wrong username/password.");
260
+ if (headers.location.includes('https://www.facebook.com/checkpoint/')) {
261
+ log.info("login", "You have login approvals turned on.");
262
+ const checkpointRes = await utils.get(headers.location, jar, null, loginOptions);
263
+ await utils.saveCookies(jar)(checkpointRes);
264
+ const checkpointHtml = checkpointRes.body;
265
+ const $ = cheerio.load(checkpointHtml);
266
+ let checkpointForm = [];
267
+ $("form input").each((i, v) => checkpointForm.push({ val: $(v).val(), name: $(v).attr("name") }));
268
+ checkpointForm = checkpointForm.filter(v => v.val && v.val.length);
269
+ const form = utils.arrToForm(checkpointForm);
270
+ if (checkpointHtml.includes("checkpoint/?next")) {
271
+ return new Promise((resolve, reject) => {
272
+ const submit2FA = async (code) => {
273
+ try {
274
+ form.approvals_code = code;
275
+ form['submit[Continue]'] = $("#checkpointSubmitButton").html();
276
+ const approvalRes = await utils.post(
277
+ "https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php",
278
+ jar,
279
+ form,
280
+ loginOptions
281
+ );
282
+ await utils.saveCookies(jar)(approvalRes);
283
+ const approvalError = $("#approvals_code").parent().attr("data-xui-error");
284
+ if (approvalError) throw new Error("Invalid 2FA code.");
285
+ form.name_action_selected = 'dont_save';
286
+ const finalRes = await utils.post(
287
+ "https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php",
288
+ jar,
289
+ form,
290
+ loginOptions
291
+ );
292
+ await utils.saveCookies(jar)(finalRes);
293
+ const appState = utils.getAppState(jar);
294
+ resolve(await loginHelper(appState, email, password, loginOptions, callback));
295
+ } catch (error) {
296
+ reject(error);
297
+ }
298
+ };
299
+ throw {
300
+ error: 'login-approval',
301
+ continue: submit2FA
302
+ };
303
+ });
304
+ }
305
+ if (!loginOptions.forceLogin) throw new Error("Couldn't login. Facebook might have blocked this account.");
306
+ form['submit[This was me]'] = checkpointHtml.includes("Suspicious Login Attempt") ? "This was me" : "This Is Okay";
307
+ await utils.post("https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php", jar, form, loginOptions);
308
+ form.name_action_selected = 'save_device';
309
+ const reviewRes = await utils.post("https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php", jar, form, loginOptions);
310
+ const appState = utils.getAppState(jar);
311
+ return await loginHelper(appState, email, password, loginOptions, callback);
312
+ }
313
+ await utils.get('https://www.facebook.com/', jar, null, loginOptions);
314
+ return await utils.saveCookies(jar);
315
+ } catch (error) {
316
+ callback(error);
317
+ }
318
+ };
323
319
  }
324
320
 
325
321
 
326
322
  function loginHelper(appState, email, password, globalOptions, callback, prCallback) {
327
- let mainPromise = null;
328
- const jar = utils.getJar();
329
- if (appState) {
330
- try {
331
- appState = JSON.parse(appState);
332
- } catch (e) {
333
- try {
334
- appState = appState;
335
- } catch (e) {
336
- return callback(new Error("Failed to parse appState"));
337
- }
338
- }
323
+ let mainPromise = null;
324
+ const jar = utils.getJar();
325
+ if (appState) {
326
+ try {
327
+ appState = JSON.parse(appState);
328
+ } catch (e) {
329
+ try {
330
+ appState = appState;
331
+ } catch (e) {
332
+ return callback(new Error("Failed to parse appState"));
333
+ }
334
+ }
339
335
 
340
- try {
341
- appState.forEach(c => {
342
- const str = `${c.key}=${c.value}; expires=${c.expires}; domain=${c.domain}; path=${c.path};`;
343
- jar.setCookie(str, "http://" + c.domain);
344
- });
336
+ try {
337
+ appState.forEach(c => {
338
+ const str = `${c.key}=${c.value}; expires=${c.expires}; domain=${c.domain}; path=${c.path};`;
339
+ jar.setCookie(str, "http://" + c.domain);
340
+ });
345
341
 
346
- mainPromise = utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true })
347
- .then(utils.saveCookies(jar));
348
- } catch (e) {
349
- process.exit(0);
350
- }
351
- } else {
352
- mainPromise = utils
353
- .get("https://www.facebook.com/", null, null, globalOptions, { noRef: true })
354
- .then(utils.saveCookies(jar))
355
- .then(makeLogin(jar, email, password, globalOptions, callback, prCallback))
356
- .then(() => utils.get('https://www.facebook.com/', jar, null, globalOptions).then(utils.saveCookies(jar)));
357
- }
342
+ mainPromise = utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true })
343
+ .then(utils.saveCookies(jar));
344
+ } catch (e) {
345
+ process.exit(0);
346
+ }
347
+ } else {
348
+ mainPromise = utils
349
+ .get("https://www.facebook.com/", null, null, globalOptions, { noRef: true })
350
+ .then(utils.saveCookies(jar))
351
+ .then(makeLogin(jar, email, password, globalOptions, callback, prCallback))
352
+ .then(() => utils.get('https://www.facebook.com/', jar, null, globalOptions).then(utils.saveCookies(jar)));
353
+ }
358
354
 
359
- function handleRedirect(res) {
360
- const reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
361
- const redirect = reg.exec(res.body);
362
- if (redirect && redirect[1]) {
363
- return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
364
- }
365
- return res;
366
- }
355
+ function handleRedirect(res) {
356
+ const reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
357
+ const redirect = reg.exec(res.body);
358
+ if (redirect && redirect[1]) {
359
+ return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
360
+ }
361
+ return res;
362
+ }
367
363
 
368
- let ctx, api;
369
- mainPromise = mainPromise
370
- .then(handleRedirect)
371
- .then(res => {
372
- const mobileAgentRegex = /MPageLoadClientMetrics/gs;
373
- if (!mobileAgentRegex.test(res.body)) {
374
- globalOptions.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36";
375
- return utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true }).then(utils.saveCookies(jar));
376
- }
377
- return res;
378
- })
379
- .then(handleRedirect)
380
- .then(res => {
381
- const html = res.body;
382
- const Obj = buildAPI(globalOptions, html, jar);
383
- ctx = Obj.ctx;
384
- api = Obj.api;
385
- return res;
386
- });
364
+ let ctx, api;
365
+ mainPromise = mainPromise
366
+ .then(handleRedirect)
367
+ .then(res => {
368
+ const mobileAgentRegex = /MPageLoadClientMetrics/gs;
369
+ if (!mobileAgentRegex.test(res.body)) {
370
+ globalOptions.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36";
371
+ return utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true }).then(utils.saveCookies(jar));
372
+ }
373
+ return res;
374
+ })
375
+ .then(handleRedirect)
376
+ .then(res => {
377
+ const html = res.body;
378
+ const Obj = buildAPI(globalOptions, html, jar);
379
+ ctx = Obj.ctx;
380
+ api = Obj.api;
381
+ return res;
382
+ });
387
383
 
388
- if (globalOptions.pageID) {
389
- mainPromise = mainPromise
390
- .then(() => utils.get(`https://www.facebook.com/${globalOptions.pageID}/messages/?section=messages&subsection=inbox`, jar, null, globalOptions))
391
- .then(resData => {
392
- let url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
393
- url = url.substring(0, url.length - 1);
394
- return utils.get('https://www.facebook.com' + url, jar, null, globalOptions);
395
- });
396
- }
384
+ if (globalOptions.pageID) {
385
+ mainPromise = mainPromise
386
+ .then(() => utils.get(`https://www.facebook.com/${globalOptions.pageID}/messages/?section=messages&subsection=inbox`, jar, null, globalOptions))
387
+ .then(resData => {
388
+ let url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
389
+ url = url.substring(0, url.length - 1);
390
+ return utils.get('https://www.facebook.com' + url, jar, null, globalOptions);
391
+ });
392
+ }
397
393
 
398
- mainPromise
399
- .then(async () => {
400
- log.info('Login successful');
401
- callback(null, api);
402
- })
403
- .catch(e => {
404
- callback(e);
405
- });
394
+ mainPromise
395
+ .then(async () => {
396
+ log.info('Login successful');
397
+ callback(null, api);
398
+ })
399
+ .catch(e => {
400
+ callback(e);
401
+ });
406
402
  }
407
403
 
408
404
 
409
405
  function login(loginData, options, callback) {
410
- if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
411
- callback = options;
412
- options = {};
413
- }
406
+ if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
407
+ callback = options;
408
+ options = {};
409
+ }
414
410
 
415
- var globalOptions = {
416
- selfListen: false,
417
- listenEvents: true,
418
- listenTyping: false,
419
- updatePresence: false,
420
- forceLogin: false,
421
- autoMarkDelivery: false,
422
- autoMarkRead: false,
423
- autoReconnect: true,
424
- logRecordSize: 100,
425
- online: false,
426
- emitReady: false,
427
- userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
428
- };
411
+ var globalOptions = {
412
+ selfListen: false,
413
+ listenEvents: false,
414
+ listenTyping: false,
415
+ updatePresence: false,
416
+ forceLogin: false,
417
+ autoMarkDelivery: false,
418
+ autoMarkRead: false,
419
+ autoReconnect: true,
420
+ logRecordSize: 100,
421
+ online: true,
422
+ emitReady: false,
423
+ userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
424
+ };
429
425
 
430
- var prCallback = null;
431
- if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
432
- var rejectFunc = null;
433
- var resolveFunc = null;
434
- var returnPromise = new Promise(function (resolve, reject) {
435
- resolveFunc = resolve;
436
- rejectFunc = reject;
437
- });
438
- prCallback = function (error, api) {
439
- if (error) return rejectFunc(error);
440
- return resolveFunc(api);
441
- };
442
- callback = prCallback;
443
- }
426
+ var prCallback = null;
427
+ if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
428
+ var rejectFunc = null;
429
+ var resolveFunc = null;
430
+ var returnPromise = new Promise(function (resolve, reject) {
431
+ resolveFunc = resolve;
432
+ rejectFunc = reject;
433
+ });
434
+ prCallback = function (error, api) {
435
+ if (error) return rejectFunc(error);
436
+ return resolveFunc(api);
437
+ };
438
+ callback = prCallback;
439
+ }
444
440
 
445
- if (loginData.email && loginData.password) {
446
- setOptions(globalOptions, {
447
- logLevel: "silent",
448
- forceLogin: true,
449
- userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
450
- });
451
- loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
452
- } else if (loginData.appState) {
453
- setOptions(globalOptions, options);
454
- return loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
455
- }
456
- return returnPromise;
441
+ if (loginData.email && loginData.password) {
442
+ setOptions(globalOptions, {
443
+ logLevel: "silent",
444
+ forceLogin: true,
445
+ userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
446
+ });
447
+ loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
448
+ } else if (loginData.appState) {
449
+ setOptions(globalOptions, options);
450
+ return loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
451
+ }
452
+ return returnPromise;
457
453
  }
458
454
 
459
455
 
460
- module.exports = login;
456
+ module.exports = login;