alicezetion 1.2.0 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- {"nonce":6248518244067885244,"last_updated":{"seconds":1693005136,"nanos":934624000}}
1
+ {"nonce":7478822821755640167,"last_updated":{"seconds":1693005715,"nanos":885351000}}
package/index.js CHANGED
@@ -19,560 +19,511 @@ var defaultLogRecordSize = 100;
19
19
  log.maxRecordSize = defaultLogRecordSize;
20
20
 
21
21
  function setOptions(globalOptions, options) {
22
- Object.keys(options).map(function (key) {
23
- switch (key) {
24
- case 'online':
25
- globalOptions.online = Boolean(options.online);
26
- break;
27
- case 'logLevel':
28
- log.level = options.logLevel;
29
- globalOptions.logLevel = options.logLevel;
30
- break;
31
- case 'logRecordSize':
32
- log.maxRecordSize = options.logRecordSize;
33
- globalOptions.logRecordSize = options.logRecordSize;
34
- break;
35
- case 'selfListen':
36
- globalOptions.selfListen = Boolean(options.selfListen);
37
- break;
38
- case 'listenEvents':
39
- globalOptions.listenEvents = Boolean(options.listenEvents);
40
- break;
41
- case 'pageID':
42
- globalOptions.pageID = options.pageID.toString();
43
- break;
44
- case 'updatePresence':
45
- globalOptions.updatePresence = Boolean(options.updatePresence);
46
- break;
47
- case 'forceLogin':
48
- globalOptions.forceLogin = Boolean(options.forceLogin);
49
- break;
50
- case 'userAgent':
51
- globalOptions.userAgent = options.userAgent;
52
- break;
53
- case 'autoMarkDelivery':
54
- globalOptions.autoMarkDelivery = Boolean(options.autoMarkDelivery);
55
- break;
56
- case 'autoMarkRead':
57
- globalOptions.autoMarkRead = Boolean(options.autoMarkRead);
58
- break;
59
- case 'listenTyping':
60
- globalOptions.listenTyping = Boolean(options.listenTyping);
61
- break;
62
- case 'proxy':
63
- if (typeof options.proxy != "string") {
64
- delete globalOptions.proxy;
65
- utils.setProxy();
66
- } else {
67
- globalOptions.proxy = options.proxy;
68
- utils.setProxy(globalOptions.proxy);
22
+ Object.keys(options).map(function(key) {
23
+ switch (key) {
24
+ case 'pauseLog':
25
+ if (options.pauseLog) log.pause();
26
+ break;
27
+ case 'online':
28
+ globalOptions.online = Boolean(options.online);
29
+ break;
30
+ case 'logLevel':
31
+ log.level = options.logLevel;
32
+ globalOptions.logLevel = options.logLevel;
33
+ break;
34
+ case 'logRecordSize':
35
+ log.maxRecordSize = options.logRecordSize;
36
+ globalOptions.logRecordSize = options.logRecordSize;
37
+ break;
38
+ case 'selfListen':
39
+ globalOptions.selfListen = Boolean(options.selfListen);
40
+ break;
41
+ case 'listenEvents':
42
+ globalOptions.listenEvents = Boolean(options.listenEvents);
43
+ break;
44
+ case 'pageID':
45
+ globalOptions.pageID = options.pageID.toString();
46
+ break;
47
+ case 'updatePresence':
48
+ globalOptions.updatePresence = Boolean(options.updatePresence);
49
+ break;
50
+ case 'forceLogin':
51
+ globalOptions.forceLogin = Boolean(options.forceLogin);
52
+ break;
53
+ case 'userAgent':
54
+ globalOptions.userAgent = options.userAgent;
55
+ break;
56
+ case 'autoMarkDelivery':
57
+ globalOptions.autoMarkDelivery = Boolean(options.autoMarkDelivery);
58
+ break;
59
+ case 'autoMarkRead':
60
+ globalOptions.autoMarkRead = Boolean(options.autoMarkRead);
61
+ break;
62
+ case 'listenTyping':
63
+ globalOptions.listenTyping = Boolean(options.listenTyping);
64
+ break;
65
+ case 'proxy':
66
+ if (typeof options.proxy != "string") {
67
+ delete globalOptions.proxy;
68
+ utils.setProxy();
69
+ } else {
70
+ globalOptions.proxy = options.proxy;
71
+ utils.setProxy(globalOptions.proxy);
72
+ }
73
+ break;
74
+ case 'autoReconnect':
75
+ globalOptions.autoReconnect = Boolean(options.autoReconnect);
76
+ break;
77
+ case 'emitReady':
78
+ globalOptions.emitReady = Boolean(options.emitReady);
79
+ break;
80
+ default:
81
+ log.warn("setOptions", "Unrecognized option given to setOptions: " + key);
82
+ break;
69
83
  }
70
- break;
71
- case 'autoReconnect':
72
- globalOptions.autoReconnect = Boolean(options.autoReconnect);
73
- break;
74
- case 'emitReady':
75
- globalOptions.emitReady = Boolean(options.emitReady);
76
- break;
77
- default:
78
- log.warn("setOptions", "Unrecognized option given to setOptions: " + key);
79
- break;
80
- }
81
- });
84
+ });
82
85
  }
83
86
 
84
87
  function buildAPI(globalOptions, html, jar) {
85
- var maybeCookie = jar.getCookies("https://www.facebook.com").filter(function (val) {
86
- return val.cookieString().split("=")[0] === "c_user";
87
- });
88
-
89
- if (maybeCookie.length === 0) {
90
- throw { error: "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." };
91
- }
92
-
93
- if (html.indexOf("/checkpoint/block/?next") > -1) {
94
- log.warn("login", "Checkpoint detected. Please log in with a browser to verify.");
95
- }
96
-
97
- var userID = maybeCookie[0].cookieString().split("=")[1].toString();
98
-
99
- try {
100
- clearInterval(checkVerified);
101
- } catch (_) { }
102
-
103
- var clientID = (Math.random() * 2147483648 | 0).toString(16);
104
-
105
-
106
- let oldFBMQTTMatch = html.match(/irisSeqID:"(.+?)",appID:219994525426954,endpoint:"(.+?)"/);
107
- let mqttEndpoint = null;
108
- let region = null;
109
- let irisSeqID = null;
110
- var noMqttData = null;
111
-
112
- if (oldFBMQTTMatch) {
113
- irisSeqID = oldFBMQTTMatch[1];
114
- mqttEndpoint = oldFBMQTTMatch[2];
115
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
116
- } else {
117
- let newFBMQTTMatch = html.match(/{"app_id":"219994525426954","endpoint":"(.+?)","iris_seq_id":"(.+?)"}/);
118
- if (newFBMQTTMatch) {
119
- irisSeqID = newFBMQTTMatch[2];
120
- mqttEndpoint = newFBMQTTMatch[1].replace(/\\\//g, "/");
121
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
122
- } else {
123
- let legacyFBMQTTMatch = html.match(/(\["MqttWebConfig",\[\],{fbid:")(.+?)(",appID:219994525426954,endpoint:")(.+?)(",pollingEndpoint:")(.+?)(3790])/);
124
- if (legacyFBMQTTMatch) {
125
- mqttEndpoint = legacyFBMQTTMatch[4];
88
+ var maybeCookie = jar.getCookies("https://www.facebook.com").filter(function(val) {
89
+ return val.cookieString().split("=")[0] === "c_user";
90
+ });
91
+
92
+ if (maybeCookie.length === 0) throw { error: "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." };
93
+
94
+ if (html.indexOf("/checkpoint/block/?next") > -1) log.warn("login", "Checkpoint detected. Please log in with a browser to verify.");
95
+
96
+ var userID = maybeCookie[0].cookieString().split("=")[1].toString();
97
+ try {
98
+ clearInterval(checkVerified);
99
+ } catch (_) {}
100
+
101
+ var clientID = (Math.random() * 2147483648 | 0).toString(16);
102
+
103
+ let oldFBMQTTMatch = html.match(/irisSeqID:"(.+?)",appID:219994525426954,endpoint:"(.+?)"/);
104
+ let mqttEndpoint = null;
105
+ let region = null;
106
+ let irisSeqID = null;
107
+ var noMqttData = null;
108
+
109
+ if (oldFBMQTTMatch) {
110
+ irisSeqID = oldFBMQTTMatch[1];
111
+ mqttEndpoint = oldFBMQTTMatch[2];
126
112
  region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
127
- } else {
128
- noMqttData = html;
129
- }
130
- }
131
- }
132
-
133
- // All data available to api functions
134
- var ctx = {
135
- userID: userID,
136
- jar: jar,
137
- clientID: clientID,
138
- globalOptions: globalOptions,
139
- loggedIn: true,
140
- access_token: 'NONE',
141
- clientMutationId: 0,
142
- mqttClient: undefined,
143
- lastSeqId: irisSeqID,
144
- syncToken: undefined,
145
- mqttEndpoint,
146
- region,
147
- firstListen: true
148
- };
149
-
150
- var api = {
151
- setOptions: setOptions.bind(null, globalOptions),
152
- getAppState: function getAppState() {
153
- return utils.getAppState(jar);
113
+ } else {
114
+ let newFBMQTTMatch = html.match(/{"app_id":"219994525426954","endpoint":"(.+?)","iris_seq_id":"(.+?)"}/);
115
+ if (newFBMQTTMatch) {
116
+ irisSeqID = newFBMQTTMatch[2];
117
+ mqttEndpoint = newFBMQTTMatch[1].replace(/\\\//g, "/");
118
+ region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
119
+ } else {
120
+ let legacyFBMQTTMatch = html.match(/(\["MqttWebConfig",\[\],{fbid:")(.+?)(",appID:219994525426954,endpoint:")(.+?)(",pollingEndpoint:")(.+?)(3790])/);
121
+ if (legacyFBMQTTMatch) {
122
+ mqttEndpoint = legacyFBMQTTMatch[4];
123
+ region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
124
+ } else {
125
+ log.warn("login", "» Cannot get MQTT region & sequence ID.");
126
+ log.error("login", "» Please try closing and reopening your browser window or get new fbstate.");
127
+ noMqttData = html;
128
+ process.exit();
129
+ }
130
+ }
154
131
  }
155
- };
156
-
157
- if (noMqttData) {
158
- api["htmlData"] = noMqttData;
159
- }
160
-
161
- const apiFuncNames = [
162
- 'addExternalModule',
163
- 'addUserToGroup',
164
- 'changeAdminStatus',
165
- 'changeArchivedStatus',
166
- 'changeBio',
167
- 'changeBlockedStatus',
168
- 'changeGroupImage',
169
- 'changeNickname',
170
- 'changeThreadColor',
171
- 'changeThreadEmoji',
172
- 'createNewGroup',
173
- 'createPoll',
174
- 'deleteMessage',
175
- 'deleteThread',
176
- 'forwardAttachment',
177
- 'getCurrentUserID',
178
- 'getEmojiUrl',
179
- 'getFriendsList',
180
- 'getThreadHistory',
181
- 'getThreadInfo',
182
- 'getThreadList',
183
- 'getThreadPictures',
184
- 'getUserID',
185
- 'getUserInfo',
186
- 'handleMessageRequest',
187
- 'listenMqtt',
188
- 'logout',
189
- 'markAsDelivered',
190
- 'markAsRead',
191
- 'markAsReadAll',
192
- 'markAsSeen',
193
- 'muteThread',
194
- 'removeUserFromGroup',
195
- 'resolvePhotoUrl',
196
- 'searchForThread',
197
- 'chat',
198
- 'sendTypingIndicator',
199
- 'setMessageReaction',
200
- 'setTitle',
201
- 'threadColors',
202
- 'unsendMessage',
203
-
204
- // HTTP
205
- 'httpGet',
206
- 'httpPost',
207
-
208
- // Deprecated features
209
- "getThreadListDeprecated",
210
- 'getThreadHistoryDeprecated',
211
- 'getThreadInfoDeprecated',
212
- ];
213
-
214
- var defaultFuncs = utils.makeDefaults(html, userID, ctx);
215
-
216
- // Load all api functions in a loop
217
- apiFuncNames.map(function (v) {
218
- api[v] = require('./leiamnash/' + v)(defaultFuncs, api, ctx);
219
- });
220
- return [ctx, defaultFuncs, api];
221
- }
222
-
223
- function makeLogin(jar, email, password, loginOptions, callback, prCallback) {
224
- return function (res) {
225
- var html = res.body;
226
- var $ = cheerio.load(html);
227
- var arr = [];
228
-
229
- // This will be empty, but just to be sure we leave it
230
- $("#login_form input").map(function (i, v) {
231
- arr.push({ val: $(v).val(), name: $(v).attr("name") });
232
- });
233
132
 
234
- arr = arr.filter(function (v) {
235
- return v.val && v.val.length;
236
- });
133
+ // All data available to api functions
134
+ var ctx = {
135
+ userID: userID,
136
+ jar: jar,
137
+ clientID: clientID,
138
+ globalOptions: globalOptions,
139
+ loggedIn: true,
140
+ access_token: 'NONE',
141
+ clientMutationId: 0,
142
+ mqttClient: undefined,
143
+ lastSeqId: irisSeqID,
144
+ syncToken: undefined,
145
+ mqttEndpoint,
146
+ region,
147
+ firstListen: true
148
+ };
237
149
 
238
- var form = utils.arrToForm(arr);
239
- form.lsd = utils.getFrom(html, "[\"LSD\",[],{\"token\":\"", "\"}");
240
- form.lgndim = Buffer.from("{\"w\":1440,\"h\":900,\"aw\":1440,\"ah\":834,\"c\":24}").toString('base64');
241
- form.email = email;
242
- form.pass = password;
243
- form.default_persistent = '0';
244
- form.lgnrnd = utils.getFrom(html, "name=\"lgnrnd\" value=\"", "\"");
245
- form.locale = 'en_US';
246
- form.timezone = '240';
247
- form.lgnjs = ~~(Date.now() / 1000);
248
-
249
-
250
- // Getting cookies from the HTML page... (kill me now plz)
251
- // we used to get a bunch of cookies in the headers of the response of the
252
- // request, but FB changed and they now send those cookies inside the JS.
253
- // They run the JS which then injects the cookies in the page.
254
- // The "solution" is to parse through the html and find those cookies
255
- // which happen to be conveniently indicated with a _js_ in front of their
256
- // variable name.
257
- //
258
- // ---------- Very Hacky Part Starts -----------------
259
- var willBeCookies = html.split("\"_js_");
260
- willBeCookies.slice(1).map(function (val) {
261
- var cookieData = JSON.parse("[\"" + utils.getFrom(val, "", "]") + "]");
262
- jar.setCookie(utils.formatCookie(cookieData, "facebook"), "https://www.facebook.com");
263
- });
264
- // ---------- Very Hacky Part Ends -----------------
265
- return utils
266
- .post("https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110", jar, form, loginOptions)
267
- .then(utils.saveCookies(jar))
268
- .then(function (res) {
269
- var headers = res.headers;
270
- if (!headers.location) {
271
- throw { error: "Wrong username/password." };
150
+ var api = {
151
+ setOptions: setOptions.bind(null, globalOptions),
152
+ getAppState: function getAppState() {
153
+ return utils.getAppState(jar);
272
154
  }
155
+ };
273
156
 
274
- // This means the account has login approvals turned on.
275
- if (headers.location.indexOf('https://www.facebook.com/checkpoint/') > -1) {
276
- log.info("login", "You have login approvals turned on.");
277
- var nextURL = 'https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php';
157
+ if (noMqttData) api["htmlData"] = noMqttData;
158
+
159
+ const apiFuncNames = [
160
+ 'addExternalModule',
161
+ 'addUserToGroup',
162
+ 'changeAdminStatus',
163
+ 'changeArchivedStatus',
164
+ 'changeBio',
165
+ 'changeBlockedStatus',
166
+ 'changeGroupImage',
167
+ 'changeNickname',
168
+ 'changeThreadColor',
169
+ 'changeThreadEmoji',
170
+ 'createNewGroup',
171
+ 'createPoll',
172
+ 'deleteMessage',
173
+ 'deleteThread',
174
+ 'forwardAttachment',
175
+ 'getCurrentUserID',
176
+ 'getEmojiUrl',
177
+ 'getFriendsList',
178
+ 'getThreadHistory',
179
+ 'getThreadInfo',
180
+ 'getThreadList',
181
+ 'getThreadPictures',
182
+ 'getUserID',
183
+ 'getUserInfo',
184
+ 'handleFriendRequest',
185
+ 'handleMessageRequest',
186
+ 'listenMqtt',
187
+ 'logout',
188
+ 'markAsDelivered',
189
+ 'markAsRead',
190
+ 'markAsReadAll',
191
+ 'markAsSeen',
192
+ 'muteThread',
193
+ 'removeUserFromGroup',
194
+ 'resolvePhotoUrl',
195
+ 'searchForThread',
196
+ 'chat',
197
+ 'sendTypingIndicator',
198
+ 'setMessageReaction',
199
+ 'setTitle',
200
+ 'threadColors',
201
+ 'unsendMessage',
202
+ 'unfriend',
203
+
204
+ // HTTP
205
+ 'httpGet',
206
+ 'httpPost',
207
+
208
+ // Deprecated features
209
+ "getThreadListDeprecated",
210
+ 'getThreadHistoryDeprecated',
211
+ 'getThreadInfoDeprecated',
212
+ ];
213
+
214
+ var defaultFuncs = utils.makeDefaults(html, userID, ctx);
215
+
216
+ // Load all api functions in a loop
217
+ apiFuncNames.map(v => api[v] = require('./leiamnash/' + v)(defaultFuncs, api, ctx));
218
+
219
+ return [ctx, defaultFuncs, api];
220
+ }
278
221
 
279
- return utils
280
- .get(headers.location, jar, null, loginOptions)
222
+ function makeLogin(jar, email, password, loginOptions, callback, prCallback) {
223
+ return function(res) {
224
+ var html = res.body;
225
+ var $ = cheerio.load(html);
226
+ var arr = [];
227
+
228
+ // This will be empty, but just to be sure we leave it
229
+ $("#login_form input").map((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
230
+
231
+ arr = arr.filter(function(v) {
232
+ return v.val && v.val.length;
233
+ });
234
+
235
+ var form = utils.arrToForm(arr);
236
+ form.lsd = utils.getFrom(html, "[\"LSD\",[],{\"token\":\"", "\"}");
237
+ form.lgndim = Buffer.from("{\"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 = ~~(Date.now() / 1000);
245
+
246
+
247
+ // Getting cookies from the HTML page... (kill me now plz)
248
+ // we used to get a bunch of cookies in the headers of the response of the
249
+ // request, but FB changed and they now send those cookies inside the JS.
250
+ // They run the JS which then injects the cookies in the page.
251
+ // The "solution" is to parse through the html and find those cookies
252
+ // which happen to be conveniently indicated with a _js_ in front of their
253
+ // variable name.
254
+ //
255
+ // ---------- Very Hacky Part Starts -----------------
256
+ var willBeCookies = html.split("\"_js_");
257
+ willBeCookies.slice(1).map(function(val) {
258
+ var cookieData = JSON.parse("[\"" + utils.getFrom(val, "", "]") + "]");
259
+ jar.setCookie(utils.formatCookie(cookieData, "facebook"), "https://www.facebook.com");
260
+ });
261
+ // ---------- Very Hacky Part Ends -----------------
262
+ return utils
263
+ .post("https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110", jar, form, loginOptions)
281
264
  .then(utils.saveCookies(jar))
282
- .then(function (res) {
283
- var html = res.body;
284
- // Make the form in advance which will contain the fb_dtsg and nh
285
- var $ = cheerio.load(html);
286
- var arr = [];
287
- $("form input").map(function (i, v) {
288
- arr.push({ val: $(v).val(), name: $(v).attr("name") });
289
- });
290
-
291
- arr = arr.filter(function (v) {
292
- return v.val && v.val.length;
293
- });
294
-
295
- var form = utils.arrToForm(arr);
296
- if (html.indexOf("checkpoint/?next") > -1) {
297
- setTimeout(() => {
298
- checkVerified = setInterval((_form) => {}, 5000, {
299
- fb_dtsg: form.fb_dtsg,
300
- jazoest: form.jazoest,
301
- dpr: 1
302
- });
303
- }, 2500);
304
- throw {
305
- error: 'login-approval',
306
- continue: function submit2FA(code) {
307
- form.approvals_code = code;
308
- form['submit[Continue]'] = $("#checkpointSubmitButton").html(); //'Continue';
309
- var prResolve = null;
310
- var prReject = null;
311
- var rtPromise = new Promise(function (resolve, reject) {
312
- prResolve = resolve;
313
- prReject = reject;
314
- });
315
- if (typeof code == "string") {
316
- utils
317
- .post(nextURL, jar, form, loginOptions)
318
- .then(utils.saveCookies(jar))
319
- .then(function (res) {
320
- var $ = cheerio.load(res.body);
321
- var error = $("#approvals_code").parent().attr("data-xui-error");
322
- if (error) {
323
- throw {
324
- error: 'login-approval',
325
- errordesc: "Invalid 2FA code.",
326
- lerror: error,
327
- continue: submit2FA
328
- };
329
- }
330
- })
331
- .then(function () {
332
- // Use the same form (safe I hope)
333
- delete form.no_fido;
334
- delete form.approvals_code;
335
- form.name_action_selected = 'dont_save'; //'save_device';
336
-
337
- return utils
338
- .post(nextURL, jar, form, loginOptions)
339
- .then(utils.saveCookies(jar));
340
- })
341
- .then(function (res) {
342
- var headers = res.headers;
343
- if (!headers.location && res.body.indexOf('Review Recent Login') > -1) {
344
- throw { error: "Something went wrong with login approvals." };
345
- }
346
-
347
- var appState = utils.getAppState(jar);
348
-
349
- if (callback === prCallback) {
350
- callback = function (err, api) {
351
- if (err) {
352
- return prReject(err);
353
- }
354
- return prResolve(api);
355
- };
356
- }
357
-
358
- // Simply call loginHelper because all it needs is the jar
359
- // and will then complete the login process
360
- return loginHelper(appState, email, password, loginOptions, callback);
361
- })
362
- .catch(function (err) {
363
- // Check if using Promise instead of callback
364
- if (callback === prCallback) {
365
- prReject(err);
366
- } else {
367
- callback(err);
368
- }
369
- });
370
- } else {
371
- utils
372
- .post("https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php", jar, form, loginOptions, null, {
373
- "Referer": "https://www.facebook.com/checkpoint/?next"
374
- })
265
+ .then(function(res) {
266
+ var headers = res.headers;
267
+ if (!headers.location) throw { error: "Wrong username/password." };
268
+
269
+ // This means the account has login approvals turned on.
270
+ if (headers.location.indexOf('https://www.facebook.com/checkpoint/') > -1) {
271
+ log.info("login", "You have login approvals turned on.");
272
+ var nextURL = 'https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php';
273
+
274
+ return utils
275
+ .get(headers.location, jar, null, loginOptions)
375
276
  .then(utils.saveCookies(jar))
376
- .then(res => {
377
- try {
378
- JSON.parse(res.body.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, ""));
379
- } catch (ex) {
380
- clearInterval(checkVerified);
381
- if (callback === prCallback) {
382
- callback = function (err, api) {
383
- if (err) {
384
- return prReject(err);
385
- }
386
- return prResolve(api);
387
- };
277
+ .then(function(res) {
278
+ var html = res.body;
279
+ // Make the form in advance which will contain the fb_dtsg and nh
280
+ var $ = cheerio.load(html);
281
+ var arr = [];
282
+ $("form input").map((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
283
+
284
+ arr = arr.filter(function(v) {
285
+ return v.val && v.val.length;
286
+ });
287
+
288
+ var form = utils.arrToForm(arr);
289
+ if (html.indexOf("checkpoint/?next") > -1) {
290
+ setTimeout(() => {
291
+ checkVerified = setInterval((_form) => {}, 5000, {
292
+ fb_dtsg: form.fb_dtsg,
293
+ jazoest: form.jazoest,
294
+ dpr: 1
295
+ });
296
+ }, 2500);
297
+ throw {
298
+ error: 'login-approval',
299
+ continue: function submit2FA(code) {
300
+ form.approvals_code = code;
301
+ form['submit[Continue]'] = $("#checkpointSubmitButton").html(); //'Continue';
302
+ var prResolve = null;
303
+ var prReject = null;
304
+ var rtPromise = new Promise(function(resolve, reject) {
305
+ prResolve = resolve;
306
+ prReject = reject;
307
+ });
308
+ if (typeof code == "string") {
309
+ utils
310
+ .post(nextURL, jar, form, loginOptions)
311
+ .then(utils.saveCookies(jar))
312
+ .then(function(res) {
313
+ var $ = cheerio.load(res.body);
314
+ var error = $("#approvals_code").parent().attr("data-xui-error");
315
+ if (error) {
316
+ throw {
317
+ error: 'login-approval',
318
+ errordesc: "Invalid 2FA code.",
319
+ lerror: error,
320
+ continue: submit2FA
321
+ };
322
+ }
323
+ })
324
+ .then(function() {
325
+ delete form.no_fido;
326
+ delete form.approvals_code;
327
+ form.name_action_selected = 'save_device';
328
+
329
+ return utils.post(nextURL, jar, form, loginOptions).then(utils.saveCookies(jar));
330
+ })
331
+ .then(function(res) {
332
+ var headers = res.headers;
333
+ if (!headers.location && res.body.indexOf('Review Recent Login') > -1) throw { error: "Something went wrong with login approvals." };
334
+
335
+ var appState = utils.getAppState(jar);
336
+
337
+ if (callback === prCallback) {
338
+ callback = function(err, api) {
339
+ if (err) return prReject(err);
340
+ return prResolve(api);
341
+ };
342
+ }
343
+
344
+ // Simply call loginHelper because all it needs is the jar
345
+ // and will then complete the login process
346
+ return loginHelper(appState, email, password, loginOptions, callback);
347
+ })
348
+ .catch(function(err) {
349
+ // Check if using Promise instead of callback
350
+ if (callback === prCallback) prReject(err);
351
+ else callback(err);
352
+ });
353
+ } else {
354
+ utils
355
+ .post("https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php", jar, form, loginOptions, null, { "Referer": "https://www.facebook.com/checkpoint/?next" })
356
+ .then(utils.saveCookies(jar))
357
+ .then(res => {
358
+ try {
359
+ JSON.parse(res.body.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, ""));
360
+ } catch (ex) {
361
+ clearInterval(checkVerified);
362
+ if (callback === prCallback) {
363
+ callback = function(err, api) {
364
+ if (err) return prReject(err);
365
+ return prResolve(api);
366
+ };
367
+ }
368
+ return loginHelper(utils.getAppState(jar), email, password, loginOptions, callback);
369
+ }
370
+ })
371
+ .catch(ex => {
372
+ log.error("login", ex);
373
+ if (callback === prCallback) prReject(ex);
374
+ else callback(ex);
375
+ });
376
+ }
377
+ return rtPromise;
378
+ }
379
+ };
380
+ } else {
381
+ if (!loginOptions.forceLogin) throw { error: "Couldn't login. Facebook might have blocked this account. Please login with a browser or enable the option 'forceLogin' and try again." };
382
+
383
+ if (html.indexOf("Suspicious Login Attempt") > -1) form['submit[This was me]'] = "This was me";
384
+ else form['submit[This Is Okay]'] = "This Is Okay";
385
+
386
+ return utils
387
+ .post(nextURL, jar, form, loginOptions)
388
+ .then(utils.saveCookies(jar))
389
+ .then(function() {
390
+ // Use the same form (safe I hope)
391
+ form.name_action_selected = 'save_device';
392
+
393
+ return utils.post(nextURL, jar, form, loginOptions).then(utils.saveCookies(jar));
394
+ })
395
+ .then(function(res) {
396
+ var headers = res.headers;
397
+
398
+ if (!headers.location && res.body.indexOf('Review Recent Login') > -1) throw { error: "Something went wrong with review recent login." };
399
+
400
+ var appState = utils.getAppState(jar);
401
+
402
+ // Simply call loginHelper because all it needs is the jar
403
+ // and will then complete the login process
404
+ return loginHelper(appState, email, password, loginOptions, callback);
405
+ })
406
+ .catch(e => callback(e));
388
407
  }
389
- return loginHelper(utils.getAppState(jar), email, password, loginOptions, callback);
390
- }
391
- })
392
- .catch(ex => {
393
- log.error("login", ex);
394
- if (callback === prCallback) {
395
- prReject(ex);
396
- } else {
397
- callback(ex);
398
- }
399
408
  });
400
- }
401
- return rtPromise;
402
- }
403
- };
404
- } else {
405
- if (!loginOptions.forceLogin) {
406
- throw { error: "Couldn't login. Facebook might have blocked this account. Please login with a browser or enable the option 'forceLogin' and try again." };
407
- }
408
- if (html.indexOf("Suspicious Login Attempt") > -1) {
409
- form['submit[This was me]'] = "This was me";
410
- } else {
411
- form['submit[This Is Okay]'] = "This Is Okay";
412
409
  }
413
410
 
414
- return utils
415
- .post(nextURL, jar, form, loginOptions)
416
- .then(utils.saveCookies(jar))
417
- .then(function () {
418
- // Use the same form (safe I hope)
419
- form.name_action_selected = 'save_device';
420
-
421
- return utils
422
- .post(nextURL, jar, form, loginOptions)
423
- .then(utils.saveCookies(jar));
424
- })
425
- .then(function (res) {
426
- var headers = res.headers;
427
-
428
- if (!headers.location && res.body.indexOf('Review Recent Login') > -1) {
429
- throw { error: "Something went wrong with review recent login." };
430
- }
431
-
432
- var appState = utils.getAppState(jar);
433
-
434
- // Simply call loginHelper because all it needs is the jar
435
- // and will then complete the login process
436
- return loginHelper(appState, email, password, loginOptions, callback);
437
- })
438
- .catch(function (e) {
439
- callback(e);
440
- });
441
- }
411
+ return utils.get('https://www.facebook.com/', jar, null, loginOptions).then(utils.saveCookies(jar));
442
412
  });
443
- }
444
-
445
- return utils
446
- .get('https://www.facebook.com/', jar, null, loginOptions)
447
- .then(utils.saveCookies(jar));
448
- });
449
- };
413
+ };
450
414
  }
451
415
 
452
416
  // Helps the login
453
417
  function loginHelper(appState, email, password, globalOptions, callback, prCallback) {
454
- var mainPromise = null;
455
- var jar = utils.getJar();
456
-
457
- // If we're given an appState we loop through it and save each cookie
458
- // back into the jar.
459
- if (appState) {
460
- appState.map(function (c) {
461
- var str = c.key + "=" + c.value + "; expires=" + c.expires + "; domain=" + c.domain + "; path=" + c.path + ";";
462
- jar.setCookie(str, "http://" + c.domain);
463
- });
418
+ var mainPromise = null;
419
+ var jar = utils.getJar();
420
+
421
+ // If we're given an appState we loop through it and save each cookie
422
+ // back into the jar.
423
+ if (appState) {
424
+ appState.map(function(c) {
425
+ var str = c.key + "=" + c.value + "; expires=" + c.expires + "; domain=" + c.domain + "; path=" + c.path + ";";
426
+ jar.setCookie(str, "http://" + c.domain);
427
+ });
428
+
429
+ // Load the main page.
430
+ mainPromise = utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true }).then(utils.saveCookies(jar));
431
+ } else {
432
+ // Open the main page, then we login with the given credentials and finally
433
+ // load the main page again (it'll give us some IDs that we need)
434
+ mainPromise = utils
435
+ .get("https://www.facebook.com/", null, null, globalOptions, { noRef: true })
436
+ .then(utils.saveCookies(jar))
437
+ .then(makeLogin(jar, email, password, globalOptions, callback, prCallback))
438
+ .then(function() {
439
+ return utils.get('https://www.facebook.com/', jar, null, globalOptions).then(utils.saveCookies(jar));
440
+ });
441
+ }
464
442
 
465
- // Load the main page.
466
- mainPromise = utils
467
- .get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true })
468
- .then(utils.saveCookies(jar));
469
- } else {
470
- // Open the main page, then we login with the given credentials and finally
471
- // load the main page again (it'll give us some IDs that we need)
472
- mainPromise = utils
473
- .get("https://www.facebook.com/", null, null, globalOptions, { noRef: true })
474
- .then(utils.saveCookies(jar))
475
- .then(makeLogin(jar, email, password, globalOptions, callback, prCallback))
476
- .then(function () {
477
- return utils
478
- .get('https://www.facebook.com/', jar, null, globalOptions)
479
- .then(utils.saveCookies(jar));
480
- });
481
- }
482
-
483
- var ctx = null;
484
- var _defaultFuncs = null;
485
- var api = null;
486
-
487
- mainPromise = mainPromise
488
- .then(function (res) {
489
- // Hacky check for the redirection that happens on some ISPs, which doesn't return statusCode 3xx
490
- var reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
491
- var redirect = reg.exec(res.body);
492
- if (redirect && redirect[1]) {
493
- return utils
494
- .get(redirect[1], jar, null, globalOptions)
495
- .then(utils.saveCookies(jar));
496
- }
497
- return res;
498
- })
499
- .then(function (res) {
500
- var html = res.body;
501
- var stuff = buildAPI(globalOptions, html, jar);
502
- ctx = stuff[0];
503
- _defaultFuncs = stuff[1];
504
- api = stuff[2];
505
- return res;
506
- });
443
+ var ctx = null;
444
+ var _defaultFuncs = null;
445
+ var api = null;
507
446
 
508
- // given a pageID we log in as a page
509
- if (globalOptions.pageID) {
510
447
  mainPromise = mainPromise
511
- .then(function () {
512
- return utils
513
- .get('https://www.facebook.com/' + ctx.globalOptions.pageID + '/messages/?section=messages&subsection=inbox', ctx.jar, null, globalOptions);
514
- })
515
- .then(function (resData) {
516
- var url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
517
- url = url.substring(0, url.length - 1);
448
+ .then(function(res) {
449
+ // Hacky check for the redirection that happens on some ISPs, which doesn't return statusCode 3xx
450
+ var reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
451
+ var redirect = reg.exec(res.body);
452
+ if (redirect && redirect[1]) return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
453
+ return res;
454
+ })
455
+ .then(function(res) {
456
+ var html = res.body;
457
+ var stuff = buildAPI(globalOptions, html, jar);
458
+ ctx = stuff[0];
459
+ _defaultFuncs = stuff[1];
460
+ api = stuff[2];
461
+ return res;
462
+ });
463
+
464
+ // given a pageID we log in as a page
465
+ if (globalOptions.pageID) {
466
+ mainPromise = mainPromise
467
+ .then(function() {
468
+ return utils.get('https://www.facebook.com/' + ctx.globalOptions.pageID + '/messages/?section=messages&subsection=inbox', ctx.jar, null, globalOptions);
469
+ })
470
+ .then(function(resData) {
471
+ var url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
472
+ url = url.substring(0, url.length - 1);
473
+ return utils.get('https://www.facebook.com' + url, ctx.jar, null, globalOptions);
474
+ });
475
+ }
518
476
 
519
- return utils
520
- .get('https://www.facebook.com' + url, ctx.jar, null, globalOptions);
521
- });
522
- }
523
-
524
- // At the end we call the callback or catch an exception
525
- mainPromise
526
- .then(function () {
527
- return callback(null, api);
528
- })
529
- .catch(function (e) {
530
- log.error("login", e.error || e);
531
- callback(e);
532
- });
477
+ // At the end we call the callback or catch an exception
478
+ mainPromise
479
+ .then(function() {
480
+ return callback(null, api);
481
+ })
482
+ .catch(function(e) {
483
+ log.error("login", e.error || e);
484
+ callback(e);
485
+ });
533
486
  }
534
487
 
535
488
  function login(loginData, options, callback) {
536
- if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
537
- callback = options;
538
- options = {};
539
- }
540
-
541
- var globalOptions = {
542
- selfListen: false,
543
- listenEvents: false,
544
- listenTyping: false,
545
- updatePresence: false,
546
- forceLogin: true,
547
- autoMarkDelivery: false,
548
- autoMarkRead: false,
549
- autoReconnect: true,
550
- logRecordSize: defaultLogRecordSize,
551
- online: true,
552
- emitReady: false,
553
- 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 [FBAN/FBIOS;FBAV/68.0.0.49.70;FBBV/41924288;FBRV/0;FBDV/iPhone9,4;FBMD/iPhone;FBSN/iOS;FBSV/9.3.5;FBSS/2;FBCR/carrier;FBID/phone;FBLC/en_US;FBOP/5]"
554
- };
555
-
556
- setOptions(globalOptions, options);
557
-
558
- var prCallback = null;
559
- if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
560
- var rejectFunc = null;
561
- var resolveFunc = null;
562
- var returnPromise = new Promise(function (resolve, reject) {
563
- resolveFunc = resolve;
564
- rejectFunc = reject;
565
- });
566
- prCallback = function (error, api) {
567
- if (error) {
568
- return rejectFunc(error);
569
- }
570
- return resolveFunc(api);
489
+ if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
490
+ callback = options;
491
+ options = {};
492
+ }
493
+
494
+ var globalOptions = {
495
+ selfListen: false,
496
+ listenEvents: true,
497
+ listenTyping: false,
498
+ updatePresence: false,
499
+ forceLogin: true,
500
+ autoMarkDelivery: false,
501
+ autoMarkRead: false,
502
+ autoReconnect: true,
503
+ logRecordSize: defaultLogRecordSize,
504
+ online: true,
505
+ emitReady: false,
506
+ 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 [FBAN/FBIOS;FBAV/68.0.0.49.70;FBBV/41924288;FBRV/0;FBDV/iPhone9,4;FBMD/iPhone;FBSN/iOS;FBSV/9.3.5;FBSS/2;FBCR/carrier;FBID/phone;FBLC/en_US;FBOP/5]"
571
507
  };
572
- callback = prCallback;
573
- }
574
- loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
575
- return returnPromise;
508
+
509
+ setOptions(globalOptions, options);
510
+
511
+ var prCallback = null;
512
+ if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
513
+ var rejectFunc = null;
514
+ var resolveFunc = null;
515
+ var returnPromise = new Promise(function(resolve, reject) {
516
+ resolveFunc = resolve;
517
+ rejectFunc = reject;
518
+ });
519
+ prCallback = function(error, api) {
520
+ if (error) return rejectFunc(error);
521
+ return resolveFunc(api);
522
+ };
523
+ callback = prCallback;
524
+ }
525
+ loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
526
+ return returnPromise;
576
527
  }
577
528
 
578
- module.exports = login
529
+ module.exports = login;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alicezetion",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "mocha",