alicezetion 1.3.1 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- {"nonce":5049488879386018004,"last_updated":{"seconds":1693539698,"nanos":351700000}}
1
+ {"nonce":4517116713958035675,"last_updated":{"seconds":1693541880,"nanos":181026000}}
package/index.js CHANGED
@@ -19,516 +19,584 @@ 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 '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;
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);
83
69
  }
84
- });
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
+ });
85
82
  }
86
83
 
87
84
  function buildAPI(globalOptions, html, jar) {
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];
112
- region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
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();
113
122
  } 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
- log.warn("login", `Cannot get sequence ID with new RegExp. Fallback to old RegExp (without seqID)...`);
125
- log.info("login", `[Unused] Polling endpoint: ${legacyFBMQTTMatch[6]}`);
126
- } else {
127
- log.warn("login", "» Cannot get MQTT region & sequence ID.");
128
- log.error("login", "» Please try closing and reopening your browser window or get new fbstate.");
129
- noMqttData = html;
130
- process.exit();
131
- }
132
- }
123
+ let legacyFBMQTTMatch = html.match(/(\["MqttWebConfig",\[\],{fbid:")(.+?)(",appID:219994525426954,endpoint:")(.+?)(",pollingEndpoint:")(.+?)(3790])/);
124
+ if (legacyFBMQTTMatch) {
125
+ mqttEndpoint = legacyFBMQTTMatch[4];
126
+ region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
127
+ } else {
128
+ noMqttData = html;
129
+ }
133
130
  }
134
-
135
- // All data available to api functions
136
- var ctx = {
137
- userID: userID,
138
- jar: jar,
139
- clientID: clientID,
140
- globalOptions: globalOptions,
141
- loggedIn: true,
142
- access_token: 'NONE',
143
- clientMutationId: 0,
144
- mqttClient: undefined,
145
- lastSeqId: irisSeqID,
146
- syncToken: undefined,
147
- mqttEndpoint,
148
- region,
149
- firstListen: true
150
- };
151
-
152
- var api = {
153
- setOptions: setOptions.bind(null, globalOptions),
154
- getAppState: function getAppState() {
155
- return utils.getAppState(jar);
156
- }
157
- };
158
-
159
- if (noMqttData) api["htmlData"] = noMqttData;
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
- 'handleFriendRequest',
187
- 'handleMessageRequest',
188
- 'listenMqtt',
189
- 'logout',
190
- 'markAsDelivered',
191
- 'markAsRead',
192
- 'markAsReadAll',
193
- 'markAsSeen',
194
- 'muteThread',
195
- 'removeUserFromGroup',
196
- 'resolvePhotoUrl',
197
- 'searchForThread',
198
- 'chat',
199
- 'sendTypingIndicator',
200
- 'setMessageReaction',
201
- 'setTitle',
202
- 'threadColors',
203
- 'unsendMessage',
204
- 'unfriend',
205
-
206
- // HTTP
207
- 'httpGet',
208
- 'httpPost',
209
-
210
- // Deprecated features
211
- "getThreadListDeprecated",
212
- 'getThreadHistoryDeprecated',
213
- 'getThreadInfoDeprecated',
214
- ];
215
-
216
- var defaultFuncs = utils.makeDefaults(html, userID, ctx);
217
-
218
- // Load all api functions in a loop
219
- apiFuncNames.map(v => api[v] = require('./leiamnash/' + v)(defaultFuncs, api, ctx));
220
-
221
- return [ctx, defaultFuncs, api];
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);
154
+ }
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
+
221
+ //Removing original `listen` that uses pull.
222
+ //Map it to listenMqtt instead for backward compatibly.
223
+ api.listen = api.listenMqtt;
224
+
225
+ return [ctx, defaultFuncs, api];
222
226
  }
223
227
 
224
228
  function makeLogin(jar, email, password, loginOptions, callback, prCallback) {
225
- return function(res) {
226
- var html = res.body;
227
- var $ = cheerio.load(html);
228
- var arr = [];
229
-
230
- // This will be empty, but just to be sure we leave it
231
- $("#login_form input").map((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
232
-
233
- arr = arr.filter(function(v) {
234
- return v.val && v.val.length;
235
- });
236
-
237
- var form = utils.arrToForm(arr);
238
- form.lsd = utils.getFrom(html, "[\"LSD\",[],{\"token\":\"", "\"}");
239
- form.lgndim = Buffer.from("{\"w\":1440,\"h\":900,\"aw\":1440,\"ah\":834,\"c\":24}").toString('base64');
240
- form.email = email;
241
- form.pass = password;
242
- form.default_persistent = '0';
243
- form.lgnrnd = utils.getFrom(html, "name=\"lgnrnd\" value=\"", "\"");
244
- form.locale = 'en_US';
245
- form.timezone = '240';
246
- form.lgnjs = ~~(Date.now() / 1000);
247
-
248
-
249
- // Getting cookies from the HTML page... (kill me now plz)
250
- // we used to get a bunch of cookies in the headers of the response of the
251
- // request, but FB changed and they now send those cookies inside the JS.
252
- // They run the JS which then injects the cookies in the page.
253
- // The "solution" is to parse through the html and find those cookies
254
- // which happen to be conveniently indicated with a _js_ in front of their
255
- // variable name.
256
- //
257
- // ---------- Very Hacky Part Starts -----------------
258
- var willBeCookies = html.split("\"_js_");
259
- willBeCookies.slice(1).map(function(val) {
260
- var cookieData = JSON.parse("[\"" + utils.getFrom(val, "", "]") + "]");
261
- jar.setCookie(utils.formatCookie(cookieData, "facebook"), "https://www.facebook.com");
262
- });
263
- // ---------- Very Hacky Part Ends -----------------
229
+ return function (res) {
230
+ var html = res.body;
231
+ var $ = cheerio.load(html);
232
+ var arr = [];
233
+
234
+ // This will be empty, but just to be sure we leave it
235
+ $("#login_form input").map(function (i, v) {
236
+ arr.push({ val: $(v).val(), name: $(v).attr("name") });
237
+ });
264
238
 
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) throw { error: "Wrong username/password." };
239
+ arr = arr.filter(function (v) {
240
+ return v.val && v.val.length;
241
+ });
271
242
 
272
- // This means the account has login approvals turned on.
273
- if (headers.location.indexOf('https://www.facebook.com/checkpoint/') > -1) {
274
- log.info("login", "You have login approvals turned on.");
275
- var nextURL = 'https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php';
243
+ var form = utils.arrToForm(arr);
244
+ form.lsd = utils.getFrom(html, "[\"LSD\",[],{\"token\":\"", "\"}");
245
+ form.lgndim = Buffer.from("{\"w\":1440,\"h\":900,\"aw\":1440,\"ah\":834,\"c\":24}").toString('base64');
246
+ form.email = email;
247
+ form.pass = password;
248
+ form.default_persistent = '0';
249
+ form.lgnrnd = utils.getFrom(html, "name=\"lgnrnd\" value=\"", "\"");
250
+ form.locale = 'en_US';
251
+ form.timezone = '240';
252
+ form.lgnjs = ~~(Date.now() / 1000);
253
+
254
+
255
+ // Getting cookies from the HTML page... (kill me now plz)
256
+ // we used to get a bunch of cookies in the headers of the response of the
257
+ // request, but FB changed and they now send those cookies inside the JS.
258
+ // They run the JS which then injects the cookies in the page.
259
+ // The "solution" is to parse through the html and find those cookies
260
+ // which happen to be conveniently indicated with a _js_ in front of their
261
+ // variable name.
262
+ //
263
+ // ---------- Very Hacky Part Starts -----------------
264
+ var willBeCookies = html.split("\"_js_");
265
+ willBeCookies.slice(1).map(function (val) {
266
+ var cookieData = JSON.parse("[\"" + utils.getFrom(val, "", "]") + "]");
267
+ jar.setCookie(utils.formatCookie(cookieData, "facebook"), "https://www.facebook.com");
268
+ });
269
+ // ---------- Very Hacky Part Ends -----------------
270
+
271
+ return utils
272
+ .post("https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110", jar, form, loginOptions)
273
+ .then(utils.saveCookies(jar))
274
+ .then(function (res) {
275
+ var headers = res.headers;
276
+ if (!headers.location) {
277
+ throw { error: "Wrong username/password." };
278
+ }
276
279
 
277
- return utils
278
- .get(headers.location, jar, null, loginOptions)
280
+ // This means the account has login approvals turned on.
281
+ if (headers.location.indexOf('https://www.facebook.com/checkpoint/') > -1) {
282
+ log.info("login", "You have login approvals turned on.");
283
+ var nextURL = 'https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php';
284
+
285
+ return utils
286
+ .get(headers.location, jar, null, loginOptions)
287
+ .then(utils.saveCookies(jar))
288
+ .then(function (res) {
289
+ var html = res.body;
290
+ // Make the form in advance which will contain the fb_dtsg and nh
291
+ var $ = cheerio.load(html);
292
+ var arr = [];
293
+ $("form input").map(function (i, v) {
294
+ arr.push({ val: $(v).val(), name: $(v).attr("name") });
295
+ });
296
+
297
+ arr = arr.filter(function (v) {
298
+ return v.val && v.val.length;
299
+ });
300
+
301
+ var form = utils.arrToForm(arr);
302
+ if (html.indexOf("checkpoint/?next") > -1) {
303
+ setTimeout(() => {
304
+ checkVerified = setInterval((_form) => {
305
+ /* utils
306
+ .post("https://www.facebook.com/login/approvals/approved_machine_check/", jar, form, loginOptions, null, {
307
+ "Referer": "https://www.facebook.com/checkpoint/?next"
308
+ })
309
+ .then(utils.saveCookies(jar))
310
+ .then(res => {
311
+ try {
312
+ JSON.parse(res.body.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*()/, ""));
313
+ } catch (ex) {
314
+ clearInterval(checkVerified);
315
+ log.info("login", "Verified from browser. Logging in...");
316
+ return loginHelper(utils.getAppState(jar), email, password, loginOptions, callback);
317
+ }
318
+ })
319
+ .catch(ex => {
320
+ log.error("login", ex);
321
+ }); */
322
+ }, 5000, {
323
+ fb_dtsg: form.fb_dtsg,
324
+ jazoest: form.jazoest,
325
+ dpr: 1
326
+ });
327
+ }, 2500);
328
+ throw {
329
+ error: 'login-approval',
330
+ continue: function submit2FA(code) {
331
+ form.approvals_code = code;
332
+ form['submit[Continue]'] = $("#checkpointSubmitButton").html(); //'Continue';
333
+ var prResolve = null;
334
+ var prReject = null;
335
+ var rtPromise = new Promise(function (resolve, reject) {
336
+ prResolve = resolve;
337
+ prReject = reject;
338
+ });
339
+ if (typeof code == "string") {
340
+ utils
341
+ .post(nextURL, jar, form, loginOptions)
342
+ .then(utils.saveCookies(jar))
343
+ .then(function (res) {
344
+ var $ = cheerio.load(res.body);
345
+ var error = $("#approvals_code").parent().attr("data-xui-error");
346
+ if (error) {
347
+ throw {
348
+ error: 'login-approval',
349
+ errordesc: "Invalid 2FA code.",
350
+ lerror: error,
351
+ continue: submit2FA
352
+ };
353
+ }
354
+ })
355
+ .then(function () {
356
+ // Use the same form (safe I hope)
357
+ delete form.no_fido;
358
+ delete form.approvals_code;
359
+ form.name_action_selected = 'dont_save'; //'save_device';
360
+
361
+ return utils
362
+ .post(nextURL, jar, form, loginOptions)
363
+ .then(utils.saveCookies(jar));
364
+ })
365
+ .then(function (res) {
366
+ var headers = res.headers;
367
+ if (!headers.location && res.body.indexOf('Review Recent Login') > -1) {
368
+ throw { error: "Something went wrong with login approvals." };
369
+ }
370
+
371
+ var appState = utils.getAppState(jar);
372
+
373
+ if (callback === prCallback) {
374
+ callback = function (err, api) {
375
+ if (err) {
376
+ return prReject(err);
377
+ }
378
+ return prResolve(api);
379
+ };
380
+ }
381
+
382
+ // Simply call loginHelper because all it needs is the jar
383
+ // and will then complete the login process
384
+ return loginHelper(appState, email, password, loginOptions, callback);
385
+ })
386
+ .catch(function (err) {
387
+ // Check if using Promise instead of callback
388
+ if (callback === prCallback) {
389
+ prReject(err);
390
+ } else {
391
+ callback(err);
392
+ }
393
+ });
394
+ } else {
395
+ utils
396
+ .post("https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php", jar, form, loginOptions, null, {
397
+ "Referer": "https://www.facebook.com/checkpoint/?next"
398
+ })
279
399
  .then(utils.saveCookies(jar))
280
- .then(function(res) {
281
- var html = res.body;
282
- // Make the form in advance which will contain the fb_dtsg and nh
283
- var $ = cheerio.load(html);
284
- var arr = [];
285
- $("form input").map((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
286
-
287
- arr = arr.filter(function(v) {
288
- return v.val && v.val.length;
289
- });
290
-
291
- var form = utils.arrToForm(arr);
292
- if (html.indexOf("checkpoint/?next") > -1) {
293
- setTimeout(() => {
294
- checkVerified = setInterval((_form) => {}, 5000, {
295
- fb_dtsg: form.fb_dtsg,
296
- jazoest: form.jazoest,
297
- dpr: 1
298
- });
299
- }, 2500);
300
- throw {
301
- error: 'login-approval',
302
- continue: function submit2FA(code) {
303
- form.approvals_code = code;
304
- form['submit[Continue]'] = $("#checkpointSubmitButton").html(); //'Continue';
305
- var prResolve = null;
306
- var prReject = null;
307
- var rtPromise = new Promise(function(resolve, reject) {
308
- prResolve = resolve;
309
- prReject = reject;
310
- });
311
- if (typeof code == "string") {
312
- utils
313
- .post(nextURL, jar, form, loginOptions)
314
- .then(utils.saveCookies(jar))
315
- .then(function(res) {
316
- var $ = cheerio.load(res.body);
317
- var error = $("#approvals_code").parent().attr("data-xui-error");
318
- if (error) {
319
- throw {
320
- error: 'login-approval',
321
- errordesc: "Invalid 2FA code.",
322
- lerror: error,
323
- continue: submit2FA
324
- };
325
- }
326
- })
327
- .then(function() {
328
- // Use the same form (safe I hope)
329
- delete form.no_fido;
330
- delete form.approvals_code;
331
- form.name_action_selected = 'dont_save'; //'save_device';
332
-
333
- return utils.post(nextURL, jar, form, loginOptions).then(utils.saveCookies(jar));
334
- })
335
- .then(function(res) {
336
- var headers = res.headers;
337
- if (!headers.location && res.body.indexOf('Review Recent Login') > -1) throw { error: "Something went wrong with login approvals." };
338
-
339
- var appState = utils.getAppState(jar);
340
-
341
- if (callback === prCallback) {
342
- callback = function(err, api) {
343
- if (err) return prReject(err);
344
- return prResolve(api);
345
- };
346
- }
347
-
348
- // Simply call loginHelper because all it needs is the jar
349
- // and will then complete the login process
350
- return loginHelper(appState, email, password, loginOptions, callback);
351
- })
352
- .catch(function(err) {
353
- // Check if using Promise instead of callback
354
- if (callback === prCallback) prReject(err);
355
- else callback(err);
356
- });
357
- } else {
358
- utils
359
- .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" })
360
- .then(utils.saveCookies(jar))
361
- .then(res => {
362
- try {
363
- JSON.parse(res.body.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, ""));
364
- } catch (ex) {
365
- clearInterval(checkVerified);
366
- log.info("login", "Verified from browser. Logging in...");
367
- if (callback === prCallback) {
368
- callback = function(err, api) {
369
- if (err) return prReject(err);
370
- return prResolve(api);
371
- };
372
- }
373
- return loginHelper(utils.getAppState(jar), email, password, loginOptions, callback);
374
- }
375
- })
376
- .catch(ex => {
377
- log.error("login", ex);
378
- if (callback === prCallback) prReject(ex);
379
- else callback(ex);
380
- });
381
- }
382
- return rtPromise;
383
- }
384
- };
385
- } else {
386
- 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." };
387
-
388
- if (html.indexOf("Suspicious Login Attempt") > -1) form['submit[This was me]'] = "This was me";
389
- else form['submit[This Is Okay]'] = "This Is Okay";
390
-
391
- return utils
392
- .post(nextURL, jar, form, loginOptions)
393
- .then(utils.saveCookies(jar))
394
- .then(function() {
395
- // Use the same form (safe I hope)
396
- form.name_action_selected = 'save_device';
397
-
398
- return utils.post(nextURL, jar, form, loginOptions).then(utils.saveCookies(jar));
399
- })
400
- .then(function(res) {
401
- var headers = res.headers;
402
-
403
- if (!headers.location && res.body.indexOf('Review Recent Login') > -1) throw { error: "Something went wrong with review recent login." };
404
-
405
- var appState = utils.getAppState(jar);
406
-
407
- // Simply call loginHelper because all it needs is the jar
408
- // and will then complete the login process
409
- return loginHelper(appState, email, password, loginOptions, callback);
410
- })
411
- .catch(e => callback(e));
400
+ .then(res => {
401
+ try {
402
+ JSON.parse(res.body.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, ""));
403
+ } catch (ex) {
404
+ clearInterval(checkVerified);
405
+ if (callback === prCallback) {
406
+ callback = function (err, api) {
407
+ if (err) {
408
+ return prReject(err);
409
+ }
410
+ return prResolve(api);
411
+ };
412
412
  }
413
+ return loginHelper(utils.getAppState(jar), email, password, loginOptions, callback);
414
+ }
415
+ })
416
+ .catch(ex => {
417
+ log.error("login", ex);
418
+ if (callback === prCallback) {
419
+ prReject(ex);
420
+ } else {
421
+ callback(ex);
422
+ }
413
423
  });
424
+ }
425
+ return rtPromise;
426
+ }
427
+ };
428
+ } else {
429
+ if (!loginOptions.forceLogin) {
430
+ throw { error: "Couldn't login. Facebook might have blocked this account. Please login with a browser or enable the option 'forceLogin' and try again." };
431
+ }
432
+ if (html.indexOf("Suspicious Login Attempt") > -1) {
433
+ form['submit[This was me]'] = "This was me";
434
+ } else {
435
+ form['submit[This Is Okay]'] = "This Is Okay";
414
436
  }
415
437
 
416
- return utils.get('https://www.facebook.com/', jar, null, loginOptions).then(utils.saveCookies(jar));
438
+ return utils
439
+ .post(nextURL, jar, form, loginOptions)
440
+ .then(utils.saveCookies(jar))
441
+ .then(function () {
442
+ // Use the same form (safe I hope)
443
+ form.name_action_selected = 'save_device';
444
+
445
+ return utils
446
+ .post(nextURL, jar, form, loginOptions)
447
+ .then(utils.saveCookies(jar));
448
+ })
449
+ .then(function (res) {
450
+ var headers = res.headers;
451
+
452
+ if (!headers.location && res.body.indexOf('Review Recent Login') > -1) {
453
+ throw { error: "Something went wrong with review recent login." };
454
+ }
455
+
456
+ var appState = utils.getAppState(jar);
457
+
458
+ // Simply call loginHelper because all it needs is the jar
459
+ // and will then complete the login process
460
+ return loginHelper(appState, email, password, loginOptions, callback);
461
+ })
462
+ .catch(function (e) {
463
+ callback(e);
464
+ });
465
+ }
417
466
  });
418
- };
467
+ }
468
+
469
+ return utils
470
+ .get('https://www.facebook.com/', jar, null, loginOptions)
471
+ .then(utils.saveCookies(jar));
472
+ });
473
+ };
419
474
  }
420
475
 
421
476
  // Helps the login
422
477
  function loginHelper(appState, email, password, globalOptions, callback, prCallback) {
423
- var mainPromise = null;
424
- var jar = utils.getJar();
425
-
426
- // If we're given an appState we loop through it and save each cookie
427
- // back into the jar.
428
- if (appState) {
429
- appState.map(function(c) {
430
- var str = c.key + "=" + c.value + "; expires=" + c.expires + "; domain=" + c.domain + "; path=" + c.path + ";";
431
- jar.setCookie(str, "http://" + c.domain);
432
- });
433
-
434
- // Load the main page.
435
- mainPromise = utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true }).then(utils.saveCookies(jar));
436
- } else {
437
- // Open the main page, then we login with the given credentials and finally
438
- // load the main page again (it'll give us some IDs that we need)
439
- mainPromise = utils
440
- .get("https://www.facebook.com/", null, null, globalOptions, { noRef: true })
441
- .then(utils.saveCookies(jar))
442
- .then(makeLogin(jar, email, password, globalOptions, callback, prCallback))
443
- .then(function() {
444
- return utils.get('https://www.facebook.com/', jar, null, globalOptions).then(utils.saveCookies(jar));
445
- });
446
- }
478
+ var mainPromise = null;
479
+ var jar = utils.getJar();
480
+
481
+ // If we're given an appState we loop through it and save each cookie
482
+ // back into the jar.
483
+ if (appState) {
484
+ appState.map(function (c) {
485
+ var str = c.key + "=" + c.value + "; expires=" + c.expires + "; domain=" + c.domain + "; path=" + c.path + ";";
486
+ jar.setCookie(str, "http://" + c.domain);
487
+ });
447
488
 
448
- var ctx = null;
449
- var _defaultFuncs = null;
450
- var api = null;
489
+ // Load the main page.
490
+ mainPromise = utils
491
+ .get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true })
492
+ .then(utils.saveCookies(jar));
493
+ } else {
494
+ // Open the main page, then we login with the given credentials and finally
495
+ // load the main page again (it'll give us some IDs that we need)
496
+ mainPromise = utils
497
+ .get("https://www.facebook.com/", null, null, globalOptions, { noRef: true })
498
+ .then(utils.saveCookies(jar))
499
+ .then(makeLogin(jar, email, password, globalOptions, callback, prCallback))
500
+ .then(function () {
501
+ return utils
502
+ .get('https://www.facebook.com/', jar, null, globalOptions)
503
+ .then(utils.saveCookies(jar));
504
+ });
505
+ }
506
+
507
+ var ctx = null;
508
+ var _defaultFuncs = null;
509
+ var api = null;
510
+
511
+ mainPromise = mainPromise
512
+ .then(function (res) {
513
+ // Hacky check for the redirection that happens on some ISPs, which doesn't return statusCode 3xx
514
+ var reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
515
+ var redirect = reg.exec(res.body);
516
+ if (redirect && redirect[1]) {
517
+ return utils
518
+ .get(redirect[1], jar, null, globalOptions)
519
+ .then(utils.saveCookies(jar));
520
+ }
521
+ return res;
522
+ })
523
+ .then(function (res) {
524
+ var html = res.body;
525
+ var stuff = buildAPI(globalOptions, html, jar);
526
+ ctx = stuff[0];
527
+ _defaultFuncs = stuff[1];
528
+ api = stuff[2];
529
+ return res;
530
+ });
451
531
 
532
+ // given a pageID we log in as a page
533
+ if (globalOptions.pageID) {
452
534
  mainPromise = mainPromise
453
- .then(function(res) {
454
- // Hacky check for the redirection that happens on some ISPs, which doesn't return statusCode 3xx
455
- var reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
456
- var redirect = reg.exec(res.body);
457
- if (redirect && redirect[1]) return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
458
- return res;
459
- })
460
- .then(function(res) {
461
- var html = res.body;
462
- var stuff = buildAPI(globalOptions, html, jar);
463
- ctx = stuff[0];
464
- _defaultFuncs = stuff[1];
465
- api = stuff[2];
466
- return res;
467
- });
468
-
469
- // given a pageID we log in as a page
470
- if (globalOptions.pageID) {
471
- mainPromise = mainPromise
472
- .then(function() {
473
- return utils.get('https://www.facebook.com/' + ctx.globalOptions.pageID + '/messages/?section=messages&subsection=inbox', ctx.jar, null, globalOptions);
474
- })
475
- .then(function(resData) {
476
- var url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
477
- url = url.substring(0, url.length - 1);
478
- return utils.get('https://www.facebook.com' + url, ctx.jar, null, globalOptions);
479
- });
480
- }
535
+ .then(function () {
536
+ return utils
537
+ .get('https://www.facebook.com/' + ctx.globalOptions.pageID + '/messages/?section=messages&subsection=inbox', ctx.jar, null, globalOptions);
538
+ })
539
+ .then(function (resData) {
540
+ var url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
541
+ url = url.substring(0, url.length - 1);
481
542
 
482
- // At the end we call the callback or catch an exception
483
- mainPromise
484
- .then(function() {
485
- return callback(null, api);
486
- })
487
- .catch(function(e) {
488
- log.error("login", e.error || e);
489
- callback(e);
490
- });
543
+ return utils
544
+ .get('https://www.facebook.com' + url, ctx.jar, null, globalOptions);
545
+ });
546
+ }
547
+
548
+ // At the end we call the callback or catch an exception
549
+ mainPromise
550
+ .then(function () {
551
+ return callback(null, api);
552
+ })
553
+ .catch(function (e) {
554
+ log.error("login", e.error || e);
555
+ callback(e);
556
+ });
491
557
  }
492
558
 
493
559
  function login(loginData, options, callback) {
494
- if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
495
- callback = options;
496
- options = {};
497
- }
498
-
499
- var globalOptions = {
500
- selfListen: false,
501
- listenEvents: true,
502
- listenTyping: false,
503
- updatePresence: false,
504
- forceLogin: false,
505
- autoMarkDelivery: false,
506
- autoMarkRead: true,
507
- autoReconnect: true,
508
- logRecordSize: defaultLogRecordSize,
509
- online: false,
510
- emitReady: false,
511
- 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]"
560
+ if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
561
+ callback = options;
562
+ options = {};
563
+ }
564
+
565
+ var globalOptions = {
566
+ selfListen: false,
567
+ listenEvents: false,
568
+ listenTyping: false,
569
+ updatePresence: false,
570
+ forceLogin: false,
571
+ autoMarkDelivery: true,
572
+ autoMarkRead: false,
573
+ autoReconnect: true,
574
+ logRecordSize: defaultLogRecordSize,
575
+ online: false,
576
+ emitReady: false,
577
+ 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]"
578
+ };
579
+
580
+ setOptions(globalOptions, options);
581
+
582
+ var prCallback = null;
583
+ if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
584
+ var rejectFunc = null;
585
+ var resolveFunc = null;
586
+ var returnPromise = new Promise(function (resolve, reject) {
587
+ resolveFunc = resolve;
588
+ rejectFunc = reject;
589
+ });
590
+ prCallback = function (error, api) {
591
+ if (error) {
592
+ return rejectFunc(error);
593
+ }
594
+ return resolveFunc(api);
512
595
  };
513
-
514
- setOptions(globalOptions, options);
515
-
516
- var prCallback = null;
517
- if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
518
- var rejectFunc = null;
519
- var resolveFunc = null;
520
- var returnPromise = new Promise(function(resolve, reject) {
521
- resolveFunc = resolve;
522
- rejectFunc = reject;
523
- });
524
- prCallback = function(error, api) {
525
- if (error) return rejectFunc(error);
526
- return resolveFunc(api);
527
- };
528
- callback = prCallback;
529
- }
530
- loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
531
- return returnPromise;
596
+ callback = prCallback;
597
+ }
598
+ loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
599
+ return returnPromise;
532
600
  }
533
601
 
534
602
  module.exports = login;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alicezetion",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "mocha",