alicezetion 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cache/replit/__replit_disk_meta.json +1 -1
- package/.cache/replit/nix/env.json +1 -1
- package/alice/addExternalModule.js +19 -0
- package/alice/{add.js → addUserToGroup.js} +16 -2
- package/alice/{admin.js → changeAdminStatus.js} +17 -3
- package/alice/{archive.js → changeArchivedStatus.js} +16 -2
- package/alice/changeBio.js +77 -0
- package/alice/changeBlockedStatus.js +47 -0
- package/alice/{gcimage.js → changeGroupImage.js} +16 -2
- package/alice/{nickname.js → changeNickname.js} +17 -2
- package/alice/changeThreadColor.js +71 -0
- package/alice/{emoji.js → changeThreadEmoji.js} +16 -2
- package/alice/createNewGroup.js +86 -0
- package/alice/{poll.js → createPoll.js} +18 -2
- package/alice/{deletemsg.js → deleteMessage.js} +15 -2
- package/alice/{deletegc.js → deleteThread.js} +15 -2
- package/alice/{forward.js → forwardAttachment.js} +16 -3
- package/alice/{id.js → getCurrentUserID.js} +1 -1
- package/alice/{friend.js → getFriendsList.js} +17 -3
- package/alice/{history.js → getThreadHistory.js} +19 -6
- package/alice/{gchistorydeprecated.js → getThreadHistoryDeprecated.js} +18 -1
- package/alice/{gcinfo.js → getThreadInfo.js} +49 -13
- package/alice/{gcinfodeprecated.js → getThreadInfoDeprecated.js} +17 -2
- package/alice/{gclist.js → getThreadList.js} +27 -9
- package/alice/{gclistdeprecated.js → getThreadListDeprecated.js} +1 -1
- package/alice/{gcimg.js → getThreadPictures.js} +15 -2
- package/alice/{userid.js → getUserID.js} +16 -2
- package/alice/{userinfo.js → getUserInfo.js} +18 -3
- package/alice/handleFriendRequest.js +61 -0
- package/alice/{msgrequest.js → handleMessageRequest.js} +16 -2
- package/alice/httpGet.js +52 -0
- package/alice/httpPost.js +52 -0
- package/alice/listenMqtt.js +363 -134
- package/alice/logout.js +18 -2
- package/alice/{delivered.js → markAsDelivered.js} +19 -2
- package/alice/markAsRead.js +80 -0
- package/alice/{seen.js → markAsReadAll.js} +16 -2
- package/alice/markAsSeen.js +59 -0
- package/alice/{mute.js → muteThread.js} +16 -2
- package/alice/{kick.js → removeUserFromGroup.js} +16 -2
- package/alice/{resolveimgurl.js → resolvePhotoUrl.js} +16 -2
- package/alice/{gcsearch.js → searchForThread.js} +16 -2
- package/alice/{chat.js → sendMessage.js} +78 -34
- package/alice/sendTypingIndicator.js +103 -0
- package/alice/{react.js → setMessageReaction.js} +39 -4
- package/alice/setPostReaction.js +76 -0
- package/alice/{title.js → setTitle.js} +16 -3
- package/alice/threadColors.js +57 -0
- package/alice/unfriend.js +52 -0
- package/alice/{unsend.js → unsendMessage.js} +16 -2
- package/index.js +324 -143
- package/package.json +27 -18
- package/utils.js +137 -61
- package/.cache/replit/modules.stamp +0 -0
- package/README.md +0 -40
- package/alice/block.js +0 -72
- package/alice/color.js +0 -53
- package/alice/gcolor.js +0 -22
- package/alice/listen.js +0 -553
- package/alice/read.js +0 -52
- package/alice/typeindicator.js +0 -77
- /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",
|
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:
|
77
|
-
syncToken: undefined
|
141
|
+
lastSeqId: irisSeqID,
|
142
|
+
syncToken: undefined,
|
143
|
+
mqttEndpoint,
|
144
|
+
region,
|
145
|
+
firstListen: true
|
78
146
|
};
|
79
147
|
|
80
|
-
var
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
-
|
215
|
+
apiFuncNames.map(function (v) {
|
216
|
+
api[v] = require('./alice/' + v)(defaultFuncs, api, ctx);
|
136
217
|
});
|
137
218
|
|
138
|
-
|
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 = '
|
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
|
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
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
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(
|
234
|
-
|
235
|
-
|
236
|
-
|
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(
|
246
|
-
|
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
|
331
|
-
var
|
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
|
-
|
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
|
-
|
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
|
-
|
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;
|