metacord 0.0.1-security → 1.2.0-Beta
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.
Potentially problematic release.
This version of metacord might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/MetaCord_Config.json +11 -0
- package/MetaCord_Database/Database.sqlite +0 -0
- package/MetaCord_Database/Do not delete this folder or any of the files in it +0 -0
- package/README.md +207 -5
- package/index.js +678 -0
- package/logger.js +16 -0
- package/package.json +38 -3
- package/src/addExternalModule.js +16 -0
- package/src/addUserToGroup.js +78 -0
- package/src/changeAdminStatus.js +78 -0
- package/src/changeArchivedStatus.js +41 -0
- package/src/changeBio.js +65 -0
- package/src/changeBlockedStatus.js +36 -0
- package/src/changeGroupImage.js +106 -0
- package/src/changeNickname.js +45 -0
- package/src/changeThreadColor.js +62 -0
- package/src/changeThreadEmoji.js +42 -0
- package/src/createNewGroup.js +70 -0
- package/src/createPoll.js +60 -0
- package/src/deleteMessage.js +45 -0
- package/src/deleteThread.js +43 -0
- package/src/forwardAttachment.js +48 -0
- package/src/getCurrentUserID.js +7 -0
- package/src/getEmojiUrl.js +27 -0
- package/src/getFriendsList.js +73 -0
- package/src/getOnlineTime.js +31 -0
- package/src/getThreadHistory.js +193 -0
- package/src/getThreadInfo.js +197 -0
- package/src/getThreadList.js +213 -0
- package/src/getThreadPictures.js +59 -0
- package/src/getUID.js +57 -0
- package/src/getUserID.js +62 -0
- package/src/getUserInfo.js +66 -0
- package/src/handleFriendRequest.js +49 -0
- package/src/handleMessageRequest.js +49 -0
- package/src/httpGet.js +49 -0
- package/src/httpPost.js +48 -0
- package/src/httpPostFormData.js +41 -0
- package/src/listenMqtt.js +634 -0
- package/src/logout.js +68 -0
- package/src/markAsDelivered.js +48 -0
- package/src/markAsRead.js +70 -0
- package/src/markAsReadAll.js +43 -0
- package/src/markAsSeen.js +51 -0
- package/src/muteThread.js +47 -0
- package/src/removeUserFromGroup.js +49 -0
- package/src/resolvePhotoUrl.js +37 -0
- package/src/searchForThread.js +43 -0
- package/src/sendMessage.js +334 -0
- package/src/sendTypingIndicator.js +80 -0
- package/src/setMessageReaction.js +109 -0
- package/src/setPostReaction.js +102 -0
- package/src/setTitle.js +74 -0
- package/src/threadColors.js +39 -0
- package/src/unfriend.js +43 -0
- package/src/unsendMessage.js +40 -0
- package/utils/Database.js +42 -0
- package/utils/Extension.js +143 -0
- package/utils/Html/MetaCord.png +0 -0
- package/utils/Html/index.html +200 -0
- package/utils/StateCrypt.js +53 -0
- package/utils.js +1249 -0
    
        package/index.js
    ADDED
    
    | @@ -0,0 +1,678 @@ | |
| 1 | 
            +
            'use strict';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            // Max Core CPU
         | 
| 4 | 
            +
            const os = require('os');
         | 
| 5 | 
            +
            process.env.UV_THREADPOOL_SIZE = os.cpus().length;
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            var utils = require("./utils");
         | 
| 8 | 
            +
            var cheerio = require("cheerio");
         | 
| 9 | 
            +
            var log = require("npmlog");
         | 
| 10 | 
            +
            var logger = require('./logger');
         | 
| 11 | 
            +
            var fs = require('fs');
         | 
| 12 | 
            +
            var StateCrypt = require('./utils/StateCrypt');
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            var extension = require('./utils/Extension');
         | 
| 15 | 
            +
            var { getKeyValue, setKeyValue } = require('./utils/Database');
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            var checkVerified = null;
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            var defaultLogRecordSize = 100;
         | 
| 20 | 
            +
            log.maxRecordSize = defaultLogRecordSize;
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            var configPath = process.cwd() + '/MetaCord_Config.json';
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            const defaultConfig = require("./MetaCord_Config.json");
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            if (!fs.existsSync(configPath)) {
         | 
| 27 | 
            +
                fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
         | 
| 28 | 
            +
            }
         | 
| 29 | 
            +
            var config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            if (config.Create_Html_Site.Enable) {
         | 
| 32 | 
            +
                extension.CreateSiteHtml(config.Create_Html_Site.Port);
         | 
| 33 | 
            +
            }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            if (config.Auto_Uptime) {
         | 
| 36 | 
            +
                const REPL_HOME = `https://${process.env.REPL_SLUG}.${process.env.REPL_OWNER}.repl.co`.toLowerCase();
         | 
| 37 | 
            +
                extension.Uptime(REPL_HOME);
         | 
| 38 | 
            +
            }
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            if (config.Count_Online_Time) {
         | 
| 41 | 
            +
                extension.StartCountOnlineTime();
         | 
| 42 | 
            +
            }
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            function setOptions(globalOptions, options) {
         | 
| 45 | 
            +
                Object.keys(options).map(function (key) {
         | 
| 46 | 
            +
                    switch (key) {
         | 
| 47 | 
            +
                        case 'pauseLog':
         | 
| 48 | 
            +
                            if (options.pauseLog) log.pause();
         | 
| 49 | 
            +
                            break;
         | 
| 50 | 
            +
                        case 'online':
         | 
| 51 | 
            +
                            globalOptions.online = Boolean(options.online);
         | 
| 52 | 
            +
                            break;
         | 
| 53 | 
            +
                        case 'logLevel':
         | 
| 54 | 
            +
                            log.level = options.logLevel;
         | 
| 55 | 
            +
                            globalOptions.logLevel = options.logLevel;
         | 
| 56 | 
            +
                            break;
         | 
| 57 | 
            +
                        case 'logRecordSize':
         | 
| 58 | 
            +
                            log.maxRecordSize = options.logRecordSize;
         | 
| 59 | 
            +
                            globalOptions.logRecordSize = options.logRecordSize;
         | 
| 60 | 
            +
                            break;
         | 
| 61 | 
            +
                        case 'selfListen':
         | 
| 62 | 
            +
                            globalOptions.selfListen = Boolean(options.selfListen);
         | 
| 63 | 
            +
                            break;
         | 
| 64 | 
            +
                        case 'listenEvents':
         | 
| 65 | 
            +
                            globalOptions.listenEvents = Boolean(options.listenEvents);
         | 
| 66 | 
            +
                            break;
         | 
| 67 | 
            +
                        case 'pageID':
         | 
| 68 | 
            +
                            globalOptions.pageID = options.pageID.toString();
         | 
| 69 | 
            +
                            break;
         | 
| 70 | 
            +
                        case 'updatePresence':
         | 
| 71 | 
            +
                            globalOptions.updatePresence = Boolean(options.updatePresence);
         | 
| 72 | 
            +
                            break;
         | 
| 73 | 
            +
                        case 'forceLogin':
         | 
| 74 | 
            +
                            globalOptions.forceLogin = Boolean(options.forceLogin);
         | 
| 75 | 
            +
                            break;
         | 
| 76 | 
            +
                        case 'userAgent':
         | 
| 77 | 
            +
                            globalOptions.userAgent = options.userAgent;
         | 
| 78 | 
            +
                            break;
         | 
| 79 | 
            +
                        case 'autoMarkDelivery':
         | 
| 80 | 
            +
                            globalOptions.autoMarkDelivery = Boolean(options.autoMarkDelivery);
         | 
| 81 | 
            +
                            break;
         | 
| 82 | 
            +
                        case 'autoMarkRead':
         | 
| 83 | 
            +
                            globalOptions.autoMarkRead = Boolean(options.autoMarkRead);
         | 
| 84 | 
            +
                            break;
         | 
| 85 | 
            +
                        case 'listenTyping':
         | 
| 86 | 
            +
                            globalOptions.listenTyping = Boolean(options.listenTyping);
         | 
| 87 | 
            +
                            break;
         | 
| 88 | 
            +
                        case 'proxy':
         | 
| 89 | 
            +
                            if (typeof options.proxy != "string") {
         | 
| 90 | 
            +
                                delete globalOptions.proxy;
         | 
| 91 | 
            +
                                utils.setProxy();
         | 
| 92 | 
            +
                            } else {
         | 
| 93 | 
            +
                                globalOptions.proxy = options.proxy;
         | 
| 94 | 
            +
                                utils.setProxy(globalOptions.proxy);
         | 
| 95 | 
            +
                            }
         | 
| 96 | 
            +
                            break;
         | 
| 97 | 
            +
                        case 'autoReconnect':
         | 
| 98 | 
            +
                            globalOptions.autoReconnect = Boolean(options.autoReconnect);
         | 
| 99 | 
            +
                            break;
         | 
| 100 | 
            +
                        case 'emitReady':
         | 
| 101 | 
            +
                            globalOptions.emitReady = Boolean(options.emitReady);
         | 
| 102 | 
            +
                            break;
         | 
| 103 | 
            +
                        default:
         | 
| 104 | 
            +
                            log.warn("setOptions", "Unrecognized option given to setOptions: " + key);
         | 
| 105 | 
            +
                            break;
         | 
| 106 | 
            +
                    }
         | 
| 107 | 
            +
                });
         | 
| 108 | 
            +
            }
         | 
| 109 | 
            +
             | 
| 110 | 
            +
            function buildAPI(globalOptions, html, jar) {
         | 
| 111 | 
            +
                var maybeCookie = jar.getCookies("https://www.facebook.com").filter(function (val) {
         | 
| 112 | 
            +
                    return val.cookieString().split("=")[0] === "c_user";
         | 
| 113 | 
            +
                });
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                if (maybeCookie.length === 0) throw { error: "Appstate - Your Cookie Is Wrong, Please Replace It, Or Go To Incognito Browser Then Sign In And Try Again!" };
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                if (html.indexOf("/checkpoint/block/?next") > -1) log.warn("login", "CheckPoint Detected - Can't Login, Try Logout Then Login And Get Appstate - Cookie");
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                var userID = maybeCookie[0].cookieString().split("=")[1].toString();
         | 
| 120 | 
            +
                logger(`Login At ID: ${userID}`, "[ MetaCord ]");
         | 
| 121 | 
            +
                process.env['UID'] = userID;
         | 
| 122 | 
            +
                try {
         | 
| 123 | 
            +
                    clearInterval(checkVerified);
         | 
| 124 | 
            +
                } catch (e) {
         | 
| 125 | 
            +
                    console.log(e);
         | 
| 126 | 
            +
                }
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                var clientID = (Math.random() * 2147483648 | 0).toString(16);
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                let oldFBMQTTMatch = html.match(/irisSeqID:"(.+?)",appID:219994525426954,endpoint:"(.+?)"/);
         | 
| 131 | 
            +
                let mqttEndpoint = null;
         | 
| 132 | 
            +
                let region = null;
         | 
| 133 | 
            +
                let irisSeqID = null;
         | 
| 134 | 
            +
                var noMqttData = null;
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                if (oldFBMQTTMatch) {
         | 
| 137 | 
            +
                    irisSeqID = oldFBMQTTMatch[1];
         | 
| 138 | 
            +
                    mqttEndpoint = oldFBMQTTMatch[2];
         | 
| 139 | 
            +
                    region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
         | 
| 140 | 
            +
                    logger(`Area Of Account Is: ${region}`, "[ MetaCord ]");
         | 
| 141 | 
            +
                } else {
         | 
| 142 | 
            +
                    let newFBMQTTMatch = html.match(/{"app_id":"219994525426954","endpoint":"(.+?)","iris_seq_id":"(.+?)"}/);
         | 
| 143 | 
            +
                    if (newFBMQTTMatch) {
         | 
| 144 | 
            +
                        irisSeqID = newFBMQTTMatch[2];
         | 
| 145 | 
            +
                        mqttEndpoint = newFBMQTTMatch[1].replace(/\\\//g, "/");
         | 
| 146 | 
            +
                        region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
         | 
| 147 | 
            +
                        logger(`Area Of Account Is:  ${region}`, "[ MetaCord ]");
         | 
| 148 | 
            +
                    } else {
         | 
| 149 | 
            +
                        let legacyFBMQTTMatch = html.match(/(\["MqttWebConfig",\[\],{fbid:")(.+?)(",appID:219994525426954,endpoint:")(.+?)(",pollingEndpoint:")(.+?)(3790])/);
         | 
| 150 | 
            +
                        if (legacyFBMQTTMatch) {
         | 
| 151 | 
            +
                            mqttEndpoint = legacyFBMQTTMatch[4];
         | 
| 152 | 
            +
                            region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
         | 
| 153 | 
            +
                            log.warn("login", `Cannot get sequence ID with new RegExp. Fallback to old RegExp (without seqID)...`);
         | 
| 154 | 
            +
                            logger(`Area Of Account Is: ${region}`, "[ MetaCord ]");
         | 
| 155 | 
            +
                            logger("login", `[Unused] Polling endpoint: ${legacyFBMQTTMatch[6]}`);
         | 
| 156 | 
            +
                        } else {
         | 
| 157 | 
            +
                            log.warn("login", "Can't Get ID Try Again !");
         | 
| 158 | 
            +
                            noMqttData = html;
         | 
| 159 | 
            +
                        }
         | 
| 160 | 
            +
                    }
         | 
| 161 | 
            +
                }
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                // All data available to api functions
         | 
| 164 | 
            +
                var ctx = {
         | 
| 165 | 
            +
                    userID: userID,
         | 
| 166 | 
            +
                    jar: jar,
         | 
| 167 | 
            +
                    clientID: clientID,
         | 
| 168 | 
            +
                    globalOptions: globalOptions,
         | 
| 169 | 
            +
                    loggedIn: true,
         | 
| 170 | 
            +
                    access_token: 'NONE',
         | 
| 171 | 
            +
                    clientMutationId: 0,
         | 
| 172 | 
            +
                    mqttClient: undefined,
         | 
| 173 | 
            +
                    lastSeqId: irisSeqID,
         | 
| 174 | 
            +
                    syncToken: undefined,
         | 
| 175 | 
            +
                    mqttEndpoint,
         | 
| 176 | 
            +
                    region,
         | 
| 177 | 
            +
                    firstListen: true
         | 
| 178 | 
            +
                };
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                var api = {
         | 
| 181 | 
            +
                    setOptions: setOptions.bind(null, globalOptions),
         | 
| 182 | 
            +
                    getAppState: function getAppState() {
         | 
| 183 | 
            +
                        return utils.getAppState(jar);
         | 
| 184 | 
            +
                    }
         | 
| 185 | 
            +
                };
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                if (noMqttData) api["htmlData"] = noMqttData;
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                const apiFuncNames = [
         | 
| 190 | 
            +
                    'addExternalModule',
         | 
| 191 | 
            +
                    'addUserToGroup',
         | 
| 192 | 
            +
                    'changeAdminStatus',
         | 
| 193 | 
            +
                    'changeArchivedStatus',
         | 
| 194 | 
            +
                    'changeBio',
         | 
| 195 | 
            +
                    'changeBlockedStatus',
         | 
| 196 | 
            +
                    'changeGroupImage',
         | 
| 197 | 
            +
                    'changeNickname',
         | 
| 198 | 
            +
                    'changeThreadColor',
         | 
| 199 | 
            +
                    'changeThreadEmoji',
         | 
| 200 | 
            +
                    'createNewGroup',
         | 
| 201 | 
            +
                    'createPoll',
         | 
| 202 | 
            +
                    'deleteMessage',
         | 
| 203 | 
            +
                    'deleteThread',
         | 
| 204 | 
            +
                    'forwardAttachment',
         | 
| 205 | 
            +
                    'getCurrentUserID',
         | 
| 206 | 
            +
                    'getEmojiUrl',
         | 
| 207 | 
            +
                    'getFriendsList',
         | 
| 208 | 
            +
                    'getThreadHistory',
         | 
| 209 | 
            +
                    'getThreadInfo',
         | 
| 210 | 
            +
                    'getThreadList',
         | 
| 211 | 
            +
                    'getThreadPictures',
         | 
| 212 | 
            +
                    'getUserID',
         | 
| 213 | 
            +
                    'getUserInfo',
         | 
| 214 | 
            +
                    'handleMessageRequest',
         | 
| 215 | 
            +
                    'listenMqtt',
         | 
| 216 | 
            +
                    'logout',
         | 
| 217 | 
            +
                    'markAsDelivered',
         | 
| 218 | 
            +
                    'markAsRead',
         | 
| 219 | 
            +
                    'markAsReadAll',
         | 
| 220 | 
            +
                    'markAsSeen',
         | 
| 221 | 
            +
                    'muteThread',
         | 
| 222 | 
            +
                    'removeUserFromGroup',
         | 
| 223 | 
            +
                    'resolvePhotoUrl',
         | 
| 224 | 
            +
                    'searchForThread',
         | 
| 225 | 
            +
                    'sendMessage',
         | 
| 226 | 
            +
                    'sendTypingIndicator',
         | 
| 227 | 
            +
                    'setMessageReaction',
         | 
| 228 | 
            +
                    'setTitle',
         | 
| 229 | 
            +
                    'threadColors',
         | 
| 230 | 
            +
                    'unsendMessage',
         | 
| 231 | 
            +
                    'unfriend',
         | 
| 232 | 
            +
                    'setPostReaction',
         | 
| 233 | 
            +
                    'handleFriendRequest',
         | 
| 234 | 
            +
                    'handleMessageRequest',
         | 
| 235 | 
            +
             | 
| 236 | 
            +
                    // HTTP
         | 
| 237 | 
            +
                    'httpGet',
         | 
| 238 | 
            +
                    'httpPost',
         | 
| 239 | 
            +
                    'httpPostFormData',
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                    //Modding MetaCord
         | 
| 242 | 
            +
                    'getUID',
         | 
| 243 | 
            +
                    'getOnlineTime'
         | 
| 244 | 
            +
                ];
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                var defaultFuncs = utils.makeDefaults(html, userID, ctx);
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                // Load all api functions in a loop
         | 
| 249 | 
            +
                apiFuncNames.map(v => api[v] = require('./src/' + v)(defaultFuncs, api, ctx));
         | 
| 250 | 
            +
             | 
| 251 | 
            +
                return [ctx, defaultFuncs, api];
         | 
| 252 | 
            +
            }
         | 
| 253 | 
            +
             | 
| 254 | 
            +
            function makeLogin(jar, email, password, loginOptions, callback, prCallback) {
         | 
| 255 | 
            +
                return function (res) {
         | 
| 256 | 
            +
                    var html = res.body;
         | 
| 257 | 
            +
                    var $ = cheerio.load(html);
         | 
| 258 | 
            +
                    var arr = [];
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                    // This will be empty, but just to be sure we leave it
         | 
| 261 | 
            +
                    $("#login_form input").map((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                    arr = arr.filter(function (v) {
         | 
| 264 | 
            +
                        return v.val && v.val.length;
         | 
| 265 | 
            +
                    });
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                    var form = utils.arrToForm(arr);
         | 
| 268 | 
            +
                    form.lsd = utils.getFrom(html, "[\"LSD\",[],{\"token\":\"", "\"}");
         | 
| 269 | 
            +
                    form.lgndim = Buffer.from("{\"w\":1440,\"h\":900,\"aw\":1440,\"ah\":834,\"c\":24}").toString('base64');
         | 
| 270 | 
            +
                    form.email = email;
         | 
| 271 | 
            +
                    form.pass = password;
         | 
| 272 | 
            +
                    form.default_persistent = '0';
         | 
| 273 | 
            +
                    form.lgnrnd = utils.getFrom(html, "name=\"lgnrnd\" value=\"", "\"");
         | 
| 274 | 
            +
                    form.locale = 'en_US';
         | 
| 275 | 
            +
                    form.timezone = '240';
         | 
| 276 | 
            +
                    form.lgnjs = ~~(Date.now() / 1000);
         | 
| 277 | 
            +
             | 
| 278 | 
            +
             | 
| 279 | 
            +
                    // Getting cookies from the HTML page... (kill me now plz)
         | 
| 280 | 
            +
                    // we used to get a bunch of cookies in the headers of the response of the
         | 
| 281 | 
            +
                    // request, but FB changed and they now send those cookies inside the JS.
         | 
| 282 | 
            +
                    // They run the JS which then injects the cookies in the page.
         | 
| 283 | 
            +
                    // The "solution" is to parse through the html and find those cookies
         | 
| 284 | 
            +
                    // which happen to be conveniently indicated with a _js_ in front of their
         | 
| 285 | 
            +
                    // variable name.
         | 
| 286 | 
            +
                    //
         | 
| 287 | 
            +
                    // ---------- Very Hacky Part Starts -----------------
         | 
| 288 | 
            +
                    var willBeCookies = html.split("\"_js_");
         | 
| 289 | 
            +
                    willBeCookies.slice(1).map(function (val) {
         | 
| 290 | 
            +
                        var cookieData = JSON.parse("[\"" + utils.getFrom(val, "", "]") + "]");
         | 
| 291 | 
            +
                        jar.setCookie(utils.formatCookie(cookieData, "facebook"), "https://www.facebook.com");
         | 
| 292 | 
            +
                    });
         | 
| 293 | 
            +
                    // ---------- Very Hacky Part Ends -----------------
         | 
| 294 | 
            +
             | 
| 295 | 
            +
                    logger("Logging...", "[ MetaCord ]");
         | 
| 296 | 
            +
                    return utils
         | 
| 297 | 
            +
                        .post("https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110", jar, form, loginOptions)
         | 
| 298 | 
            +
                        .then(utils.saveCookies(jar))
         | 
| 299 | 
            +
                        .then(function (res) {
         | 
| 300 | 
            +
                            var headers = res.headers;
         | 
| 301 | 
            +
                            if (!headers.location) throw { error: "Wrong Password Or Account !" };
         | 
| 302 | 
            +
             | 
| 303 | 
            +
                            // This means the account has login approvals turned on.
         | 
| 304 | 
            +
                            if (headers.location.indexOf('https://www.facebook.com/checkpoint/') > -1) {
         | 
| 305 | 
            +
                                logger("You Are On 2 Security !", "[ MetaCord ]");
         | 
| 306 | 
            +
                                var nextURL = 'https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php';
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                                return utils
         | 
| 309 | 
            +
                                    .get(headers.location, jar, null, loginOptions)
         | 
| 310 | 
            +
                                    .then(utils.saveCookies(jar))
         | 
| 311 | 
            +
                                    .then(function (res) {
         | 
| 312 | 
            +
                                        var html = res.body;
         | 
| 313 | 
            +
                                        // Make the form in advance which will contain the fb_dtsg and nh
         | 
| 314 | 
            +
                                        var $ = cheerio.load(html);
         | 
| 315 | 
            +
                                        var arr = [];
         | 
| 316 | 
            +
                                        $("form input").map((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
         | 
| 317 | 
            +
             | 
| 318 | 
            +
                                        arr = arr.filter(function (v) {
         | 
| 319 | 
            +
                                            return v.val && v.val.length;
         | 
| 320 | 
            +
                                        });
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                                        var form = utils.arrToForm(arr);
         | 
| 323 | 
            +
                                        if (html.indexOf("checkpoint/?next") > -1) {
         | 
| 324 | 
            +
                                            setTimeout(() => {
         | 
| 325 | 
            +
                                                checkVerified = setInterval((_form) => { }, 5000, {
         | 
| 326 | 
            +
                                                    fb_dtsg: form.fb_dtsg,
         | 
| 327 | 
            +
                                                    jazoest: form.jazoest,
         | 
| 328 | 
            +
                                                    dpr: 1
         | 
| 329 | 
            +
                                                });
         | 
| 330 | 
            +
                                            }, 2500);
         | 
| 331 | 
            +
                                            throw {
         | 
| 332 | 
            +
                                                error: 'login-approval',
         | 
| 333 | 
            +
                                                continue: function submit2FA(code) {
         | 
| 334 | 
            +
                                                    form.approvals_code = code;
         | 
| 335 | 
            +
                                                    form['submit[Continue]'] = $("#checkpointSubmitButton").html(); //'Continue';
         | 
| 336 | 
            +
                                                    var prResolve = null;
         | 
| 337 | 
            +
                                                    var prReject = null;
         | 
| 338 | 
            +
                                                    var rtPromise = new Promise(function (resolve, reject) {
         | 
| 339 | 
            +
                                                        prResolve = resolve;
         | 
| 340 | 
            +
                                                        prReject = reject;
         | 
| 341 | 
            +
                                                    });
         | 
| 342 | 
            +
                                                    if (typeof code == "string") {
         | 
| 343 | 
            +
                                                        utils
         | 
| 344 | 
            +
                                                            .post(nextURL, jar, form, loginOptions)
         | 
| 345 | 
            +
                                                            .then(utils.saveCookies(jar))
         | 
| 346 | 
            +
                                                            .then(function (res) {
         | 
| 347 | 
            +
                                                                var $ = cheerio.load(res.body);
         | 
| 348 | 
            +
                                                                var error = $("#approvals_code").parent().attr("data-xui-error");
         | 
| 349 | 
            +
                                                                if (error) {
         | 
| 350 | 
            +
                                                                    throw {
         | 
| 351 | 
            +
                                                                        error: 'login-approval',
         | 
| 352 | 
            +
                                                                        errordesc: "Invalid 2FA code.",
         | 
| 353 | 
            +
                                                                        lerror: error,
         | 
| 354 | 
            +
                                                                        continue: submit2FA
         | 
| 355 | 
            +
                                                                    };
         | 
| 356 | 
            +
                                                                }
         | 
| 357 | 
            +
                                                            })
         | 
| 358 | 
            +
                                                            .then(function () {
         | 
| 359 | 
            +
                                                                // Use the same form (safe I hope)
         | 
| 360 | 
            +
                                                                delete form.no_fido;
         | 
| 361 | 
            +
                                                                delete form.approvals_code;
         | 
| 362 | 
            +
                                                                form.name_action_selected = 'dont_save'; //'save_device';
         | 
| 363 | 
            +
             | 
| 364 | 
            +
                                                                return utils.post(nextURL, jar, form, loginOptions).then(utils.saveCookies(jar));
         | 
| 365 | 
            +
                                                            })
         | 
| 366 | 
            +
                                                            .then(function (res) {
         | 
| 367 | 
            +
                                                                var headers = res.headers;
         | 
| 368 | 
            +
                                                                if (!headers.location && res.body.indexOf('Review Recent Login') > -1) throw { error: "Something went wrong with login approvals." };
         | 
| 369 | 
            +
             | 
| 370 | 
            +
                                                                var appState = utils.getAppState(jar);
         | 
| 371 | 
            +
             | 
| 372 | 
            +
                                                                if (callback === prCallback) {
         | 
| 373 | 
            +
                                                                    callback = function (err, api) {
         | 
| 374 | 
            +
                                                                        if (err) return prReject(err);
         | 
| 375 | 
            +
                                                                        return prResolve(api);
         | 
| 376 | 
            +
                                                                    };
         | 
| 377 | 
            +
                                                                }
         | 
| 378 | 
            +
             | 
| 379 | 
            +
                                                                // Simply call loginHelper because all it needs is the jar
         | 
| 380 | 
            +
                                                                // and will then complete the login process
         | 
| 381 | 
            +
                                                                return loginHelper(appState, email, password, loginOptions, callback);
         | 
| 382 | 
            +
                                                            })
         | 
| 383 | 
            +
                                                            .catch(function (err) {
         | 
| 384 | 
            +
                                                                // Check if using Promise instead of callback
         | 
| 385 | 
            +
                                                                if (callback === prCallback) prReject(err);
         | 
| 386 | 
            +
                                                                else callback(err);
         | 
| 387 | 
            +
                                                            });
         | 
| 388 | 
            +
                                                    } else {
         | 
| 389 | 
            +
                                                        utils
         | 
| 390 | 
            +
                                                            .post("https://www.facebook.com/checkpoint/?next=https%3A%2F%2Fwww.facebook.com%2Fhome.php", jar, form, loginOptions, null, { "Referer": "https://www.facebook.com/checkpoint/?next" })
         | 
| 391 | 
            +
                                                            .then(utils.saveCookies(jar))
         | 
| 392 | 
            +
                                                            .then(res => {
         | 
| 393 | 
            +
                                                                try {
         | 
| 394 | 
            +
                                                                    JSON.parse(res.body.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, ""));
         | 
| 395 | 
            +
                                                                } catch (ex) {
         | 
| 396 | 
            +
                                                                    clearInterval(checkVerified);
         | 
| 397 | 
            +
                                                                    logger("Confirm From Browser, Logging In...", "[ MetaCord ]");
         | 
| 398 | 
            +
                                                                    if (callback === prCallback) {
         | 
| 399 | 
            +
                                                                        callback = function (err, api) {
         | 
| 400 | 
            +
                                                                            if (err) return prReject(err);
         | 
| 401 | 
            +
                                                                            return prResolve(api);
         | 
| 402 | 
            +
                                                                        };
         | 
| 403 | 
            +
                                                                    }
         | 
| 404 | 
            +
                                                                    return loginHelper(utils.getAppState(jar), email, password, loginOptions, callback);
         | 
| 405 | 
            +
                                                                }
         | 
| 406 | 
            +
                                                            })
         | 
| 407 | 
            +
                                                            .catch(ex => {
         | 
| 408 | 
            +
                                                                log.error("login", ex);
         | 
| 409 | 
            +
                                                                if (callback === prCallback) prReject(ex);
         | 
| 410 | 
            +
                                                                else callback(ex);
         | 
| 411 | 
            +
                                                            });
         | 
| 412 | 
            +
                                                    }
         | 
| 413 | 
            +
                                                    return rtPromise;
         | 
| 414 | 
            +
                                                }
         | 
| 415 | 
            +
                                            };
         | 
| 416 | 
            +
                                        } else {
         | 
| 417 | 
            +
                                            if (!loginOptions.forceLogin) throw { error: "Couldn't login. Facebook might have blocked this account. Please login with a browser or enable the option 'forceLogin' and try again." };
         | 
| 418 | 
            +
             | 
| 419 | 
            +
                                            if (html.indexOf("Suspicious Login Attempt") > -1) form['submit[This was me]'] = "This was me";
         | 
| 420 | 
            +
                                            else form['submit[This Is Okay]'] = "This Is Okay";
         | 
| 421 | 
            +
             | 
| 422 | 
            +
                                            return utils
         | 
| 423 | 
            +
                                                .post(nextURL, jar, form, loginOptions)
         | 
| 424 | 
            +
                                                .then(utils.saveCookies(jar))
         | 
| 425 | 
            +
                                                .then(function () {
         | 
| 426 | 
            +
                                                    // Use the same form (safe I hope)
         | 
| 427 | 
            +
                                                    form.name_action_selected = 'save_device';
         | 
| 428 | 
            +
             | 
| 429 | 
            +
                                                    return utils.post(nextURL, jar, form, loginOptions).then(utils.saveCookies(jar));
         | 
| 430 | 
            +
                                                })
         | 
| 431 | 
            +
                                                .then(function (res) {
         | 
| 432 | 
            +
                                                    var headers = res.headers;
         | 
| 433 | 
            +
             | 
| 434 | 
            +
                                                    if (!headers.location && res.body.indexOf('Review Recent Login') > -1) throw { error: "Something went wrong with review recent login." };
         | 
| 435 | 
            +
             | 
| 436 | 
            +
                                                    var appState = utils.getAppState(jar);
         | 
| 437 | 
            +
             | 
| 438 | 
            +
                                                    // Simply call loginHelper because all it needs is the jar
         | 
| 439 | 
            +
                                                    // and will then complete the login process
         | 
| 440 | 
            +
                                                    return loginHelper(appState, email, password, loginOptions, callback);
         | 
| 441 | 
            +
                                                })
         | 
| 442 | 
            +
                                                .catch(e => callback(e));
         | 
| 443 | 
            +
                                        }
         | 
| 444 | 
            +
                                    });
         | 
| 445 | 
            +
                            }
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                            return utils.get('https://www.facebook.com/', jar, null, loginOptions).then(utils.saveCookies(jar));
         | 
| 448 | 
            +
                        });
         | 
| 449 | 
            +
                };
         | 
| 450 | 
            +
            }
         | 
| 451 | 
            +
             | 
| 452 | 
            +
            function makeid(length) {
         | 
| 453 | 
            +
                var result = '';
         | 
| 454 | 
            +
                var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
         | 
| 455 | 
            +
                var charactersLength = characters.length;
         | 
| 456 | 
            +
                for (var i = 0; i < length; i++) {
         | 
| 457 | 
            +
                    result += characters.charAt(Math.floor(Math.random() *
         | 
| 458 | 
            +
                        charactersLength));
         | 
| 459 | 
            +
                }
         | 
| 460 | 
            +
                return result;
         | 
| 461 | 
            +
            }
         | 
| 462 | 
            +
             | 
| 463 | 
            +
            // Helps the login
         | 
| 464 | 
            +
            async function loginHelper(appState, email, password, globalOptions, callback, prCallback) {
         | 
| 465 | 
            +
                var mainPromise = null;
         | 
| 466 | 
            +
                var jar = utils.getJar();
         | 
| 467 | 
            +
             | 
| 468 | 
            +
                // If we're given an appState we loop through it and save each cookie
         | 
| 469 | 
            +
                // back into the jar.    
         | 
| 470 | 
            +
                try {
         | 
| 471 | 
            +
                    if (appState) {
         | 
| 472 | 
            +
             | 
| 473 | 
            +
                        if (!getKeyValue("AppstateKey1") || !getKeyValue("AppstateKey2") || !getKeyValue("AppstateKey2")) {
         | 
| 474 | 
            +
                            try {
         | 
| 475 | 
            +
                                setKeyValue("AppstateKey1", makeid(50));
         | 
| 476 | 
            +
                                setKeyValue("AppstateKey2", makeid(50));
         | 
| 477 | 
            +
                                setKeyValue("AppstateKey3", makeid(50));
         | 
| 478 | 
            +
                                logger("Generate Random Password Success !");
         | 
| 479 | 
            +
                            }
         | 
| 480 | 
            +
                            catch (e) {
         | 
| 481 | 
            +
                                console.log(e);
         | 
| 482 | 
            +
                                logger("An Error Was Found While Trying to Generate Random Password", "[ MetaCord ]");
         | 
| 483 | 
            +
                            }
         | 
| 484 | 
            +
                        }
         | 
| 485 | 
            +
             | 
| 486 | 
            +
             | 
| 487 | 
            +
                        if (getKeyValue("AppstateKey1") || getKeyValue("AppstateKey2") || getKeyValue("AppstateKey2")) {
         | 
| 488 | 
            +
                            try {
         | 
| 489 | 
            +
                                appState = JSON.stringify(appState);
         | 
| 490 | 
            +
                                if (appState.includes('[')) {
         | 
| 491 | 
            +
                                    logger('Not ready for decryption', '[ MetaCord ]')
         | 
| 492 | 
            +
                                } else {
         | 
| 493 | 
            +
                                    try {
         | 
| 494 | 
            +
                                        appState = JSON.parse(appState);
         | 
| 495 | 
            +
                                        appState = StateCrypt.decryptState(appState, getKeyValue("AppstateKey1"), getKeyValue("AppstateKey2"), getKeyValue("AppstateKey3"));
         | 
| 496 | 
            +
                                        logger('Decrypt Appstate Success !', '[ MetaCord ]');
         | 
| 497 | 
            +
                                    }
         | 
| 498 | 
            +
                                    catch (e) {
         | 
| 499 | 
            +
                                        logger('Replace AppState !', '[ MetaCord ]');
         | 
| 500 | 
            +
                                        console.log(e);
         | 
| 501 | 
            +
                                    }
         | 
| 502 | 
            +
                                }
         | 
| 503 | 
            +
                            }
         | 
| 504 | 
            +
                            catch (e) {
         | 
| 505 | 
            +
                                console.log(e);
         | 
| 506 | 
            +
                            }
         | 
| 507 | 
            +
                        }
         | 
| 508 | 
            +
                        try {
         | 
| 509 | 
            +
                            appState = JSON.parse(appState);
         | 
| 510 | 
            +
                        }
         | 
| 511 | 
            +
                        catch (e) {
         | 
| 512 | 
            +
                            try {
         | 
| 513 | 
            +
                                appState = appState;
         | 
| 514 | 
            +
                            }
         | 
| 515 | 
            +
                            catch (e) {
         | 
| 516 | 
            +
                                console.log(e);
         | 
| 517 | 
            +
                                return logger('Replace AppState !', '[ MetaCord ]')
         | 
| 518 | 
            +
                            }
         | 
| 519 | 
            +
                        }
         | 
| 520 | 
            +
                        try {
         | 
| 521 | 
            +
                            appState.map(function (c) {
         | 
| 522 | 
            +
                                var str = c.key + "=" + c.value + "; expires=" + c.expires + "; domain=" + c.domain + "; path=" + c.path + ";";
         | 
| 523 | 
            +
                                jar.setCookie(str, "http://" + c.domain);
         | 
| 524 | 
            +
                            });
         | 
| 525 | 
            +
             | 
| 526 | 
            +
                            // Load the main page.
         | 
| 527 | 
            +
                            mainPromise = utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true }).then(utils.saveCookies(jar));
         | 
| 528 | 
            +
                        } catch (e) {
         | 
| 529 | 
            +
                            console.log(e);
         | 
| 530 | 
            +
                            return logger('Replace AppState !', '[ MetaCord ]')
         | 
| 531 | 
            +
                        }
         | 
| 532 | 
            +
                    } else {
         | 
| 533 | 
            +
                        // Open the main page, then we login with the given credentials and finally
         | 
| 534 | 
            +
                        // load the main page again (it'll give us some IDs that we need)
         | 
| 535 | 
            +
                        mainPromise = utils
         | 
| 536 | 
            +
                            .get("https://www.facebook.com/", null, null, globalOptions, { noRef: true })
         | 
| 537 | 
            +
                            .then(utils.saveCookies(jar))
         | 
| 538 | 
            +
                            .then(makeLogin(jar, email, password, globalOptions, callback, prCallback))
         | 
| 539 | 
            +
                            .then(function () {
         | 
| 540 | 
            +
                                return utils.get('https://www.facebook.com/', jar, null, globalOptions).then(utils.saveCookies(jar));
         | 
| 541 | 
            +
                            });
         | 
| 542 | 
            +
                    }
         | 
| 543 | 
            +
                } catch (e) {
         | 
| 544 | 
            +
                    console.log(e);
         | 
| 545 | 
            +
                }
         | 
| 546 | 
            +
                var ctx = null;
         | 
| 547 | 
            +
                var _defaultFuncs = null;
         | 
| 548 | 
            +
                var api = null;
         | 
| 549 | 
            +
             | 
| 550 | 
            +
                mainPromise = mainPromise
         | 
| 551 | 
            +
                    .then(function (res) {
         | 
| 552 | 
            +
                        // Hacky check for the redirection that happens on some ISPs, which doesn't return statusCode 3xx
         | 
| 553 | 
            +
                        var reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
         | 
| 554 | 
            +
                        var redirect = reg.exec(res.body);
         | 
| 555 | 
            +
                        if (redirect && redirect[1]) return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
         | 
| 556 | 
            +
                        return res;
         | 
| 557 | 
            +
                    })
         | 
| 558 | 
            +
                    .then(function (res) {
         | 
| 559 | 
            +
                        var html = res.body;
         | 
| 560 | 
            +
                        var stuff = buildAPI(globalOptions, html, jar);
         | 
| 561 | 
            +
                        ctx = stuff[0];
         | 
| 562 | 
            +
                        _defaultFuncs = stuff[1];
         | 
| 563 | 
            +
                        api = stuff[2];
         | 
| 564 | 
            +
                        return res;
         | 
| 565 | 
            +
                    });
         | 
| 566 | 
            +
             | 
| 567 | 
            +
                // given a pageID we log in as a page
         | 
| 568 | 
            +
                if (globalOptions.pageID) {
         | 
| 569 | 
            +
                    mainPromise = mainPromise
         | 
| 570 | 
            +
                        .then(function () {
         | 
| 571 | 
            +
                            return utils.get('https://www.facebook.com/' + ctx.globalOptions.pageID + '/messages/?section=messages&subsection=inbox', ctx.jar, null, globalOptions);
         | 
| 572 | 
            +
                        })
         | 
| 573 | 
            +
                        .then(function (resData) {
         | 
| 574 | 
            +
                            var url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
         | 
| 575 | 
            +
                            url = url.substring(0, url.length - 1);
         | 
| 576 | 
            +
                            return utils.get('https://www.facebook.com' + url, ctx.jar, null, globalOptions);
         | 
| 577 | 
            +
                        });
         | 
| 578 | 
            +
                }
         | 
| 579 | 
            +
             | 
| 580 | 
            +
             | 
| 581 | 
            +
                // At the end we call the callback or catch an exception
         | 
| 582 | 
            +
                mainPromise
         | 
| 583 | 
            +
                    .then(function () {
         | 
| 584 | 
            +
                        logger('Complete the Login Process!', "[ MetaCord ]");
         | 
| 585 | 
            +
                        //!---------- Auto Check, Update START -----------------!//
         | 
| 586 | 
            +
                        if (config.Auto_Update) {
         | 
| 587 | 
            +
                            logger('Auto Check Update ...', "[ MetaCord ]");
         | 
| 588 | 
            +
                            var axios = require('axios');
         | 
| 589 | 
            +
                            var { readFileSync } = require('fs-extra');
         | 
| 590 | 
            +
                            const { execSync } = require('child_process');
         | 
| 591 | 
            +
                            axios.get('https://raw.githubusercontent.com/Shinchan0911/MetaCord/main/MetaCord_Config.json').then(async (res) => {
         | 
| 592 | 
            +
                                if (res.data.Config_Version != config.Config_Version) {
         | 
| 593 | 
            +
                                    logger(`New Config Version Published: ${config.Config_Version} => ${res.data.Config_Version}`, "[ MetaCord ]");
         | 
| 594 | 
            +
                                    logger(`Perform Automatic Update Config to the Latest Version !`, "[ MetaCord ]");
         | 
| 595 | 
            +
                                    await fs.writeFileSync(configPath, JSON.stringify(res.data, null, 2));
         | 
| 596 | 
            +
                                    logger("Config Version Upgrade Successful!", "[ MetaCord ]")
         | 
| 597 | 
            +
                                    logger('Restarting...', '[ MetaCord ]');
         | 
| 598 | 
            +
                                    await new Promise(resolve => setTimeout(resolve, 5 * 1000));
         | 
| 599 | 
            +
                                    console.clear(); process.exit(1);
         | 
| 600 | 
            +
                                }
         | 
| 601 | 
            +
                            });
         | 
| 602 | 
            +
                            axios.get('https://raw.githubusercontent.com/Shinchan0911/MetaCord/main/package.json').then(async (res) => {
         | 
| 603 | 
            +
                                const localbrand = JSON.parse(readFileSync('./node_modules/metacord/package.json')).version;
         | 
| 604 | 
            +
                                if (localbrand != res.data.version) {
         | 
| 605 | 
            +
                                    logger(`New Version Published: ${JSON.parse(readFileSync('./node_modules/metacord/package.json')).version} => ${res.data.version}`, "[ MetaCord ]");
         | 
| 606 | 
            +
                                    logger(`Perform Automatic Update to the Latest Version !`, "[ MetaCord ]");
         | 
| 607 | 
            +
                                    try {
         | 
| 608 | 
            +
                                        execSync('npm install shinchan0911/metacord', { stdio: 'inherit' });
         | 
| 609 | 
            +
                                        logger("Version Upgrade Successful!", "[ MetaCord ]")
         | 
| 610 | 
            +
                                        logger('Restarting...', '[ MetaCord ]');
         | 
| 611 | 
            +
                                        await new Promise(resolve => setTimeout(resolve, 5 * 1000));
         | 
| 612 | 
            +
                                        console.clear(); process.exit(1);
         | 
| 613 | 
            +
                                    }
         | 
| 614 | 
            +
                                    catch (err) {
         | 
| 615 | 
            +
                                        logger('Auto Update error ! ' + err, "[ MetaCord ]");
         | 
| 616 | 
            +
                                    }
         | 
| 617 | 
            +
                                }
         | 
| 618 | 
            +
                                else {
         | 
| 619 | 
            +
                                    logger(`You Are Currently Using Version: ` + localbrand + ' !', "[ MetaCord ]");
         | 
| 620 | 
            +
                                    logger(`And Config Version: ` + config.Config_Version + ' !', "[ MetaCord ]");
         | 
| 621 | 
            +
                                    logger(`Have a good day !`);
         | 
| 622 | 
            +
                                    await new Promise(resolve => setTimeout(resolve, 5 * 1000));
         | 
| 623 | 
            +
                                    callback(null, api);
         | 
| 624 | 
            +
                                }
         | 
| 625 | 
            +
                            });
         | 
| 626 | 
            +
                        } else return callback(null, api);
         | 
| 627 | 
            +
                    }).catch(function (e) {
         | 
| 628 | 
            +
                        log.error("login", e.error || e);
         | 
| 629 | 
            +
                        callback(e);
         | 
| 630 | 
            +
                    });
         | 
| 631 | 
            +
                //!---------- Auto Check, Update END -----------------!//
         | 
| 632 | 
            +
            }
         | 
| 633 | 
            +
             | 
| 634 | 
            +
            function login(loginData, options, callback) {
         | 
| 635 | 
            +
                if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
         | 
| 636 | 
            +
                    callback = options;
         | 
| 637 | 
            +
                    options = {};
         | 
| 638 | 
            +
                }
         | 
| 639 | 
            +
             | 
| 640 | 
            +
                var globalOptions = {
         | 
| 641 | 
            +
                    selfListen: false,
         | 
| 642 | 
            +
                    listenEvents: true,
         | 
| 643 | 
            +
                    listenTyping: true,
         | 
| 644 | 
            +
                    updatePresence: false,
         | 
| 645 | 
            +
                    forceLogin: false,
         | 
| 646 | 
            +
                    autoMarkDelivery: true,
         | 
| 647 | 
            +
                    autoMarkRead: true,
         | 
| 648 | 
            +
                    autoReconnect: true,
         | 
| 649 | 
            +
                    logRecordSize: defaultLogRecordSize,
         | 
| 650 | 
            +
                    online: true,
         | 
| 651 | 
            +
                    emitReady: false,
         | 
| 652 | 
            +
                    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"
         | 
| 653 | 
            +
                };
         | 
| 654 | 
            +
             | 
| 655 | 
            +
                //! bằng 1 cách nào đó tắt online sẽ đánh lừa được facebook :v
         | 
| 656 | 
            +
                //! phải có that có this chứ :v
         | 
| 657 | 
            +
             | 
| 658 | 
            +
                setOptions(globalOptions, options);
         | 
| 659 | 
            +
             | 
| 660 | 
            +
                var prCallback = null;
         | 
| 661 | 
            +
                if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
         | 
| 662 | 
            +
                    var rejectFunc = null;
         | 
| 663 | 
            +
                    var resolveFunc = null;
         | 
| 664 | 
            +
                    var returnPromise = new Promise(function (resolve, reject) {
         | 
| 665 | 
            +
                        resolveFunc = resolve;
         | 
| 666 | 
            +
                        rejectFunc = reject;
         | 
| 667 | 
            +
                    });
         | 
| 668 | 
            +
                    prCallback = function (error, api) {
         | 
| 669 | 
            +
                        if (error) return rejectFunc(error);
         | 
| 670 | 
            +
                        return resolveFunc(api);
         | 
| 671 | 
            +
                    };
         | 
| 672 | 
            +
                    callback = prCallback;
         | 
| 673 | 
            +
                }
         | 
| 674 | 
            +
                loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
         | 
| 675 | 
            +
                return returnPromise;
         | 
| 676 | 
            +
            }
         | 
| 677 | 
            +
             | 
| 678 | 
            +
            module.exports = login;
         |