alicezetion 1.8.4 → 1.8.6

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