alicezetion 1.0.0 → 1.0.2

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