HWM Work

try to take over the world!

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         HWM Work
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.heroeswm.ru/pl_info.php?id=*/
// @grant        none
// ==/UserScript==

(function () {
    var myBot = (() => {
        var globalVars = {
            charParams: { id: null },
            serverUrl: 'http://localhost:3000',
            hwmUrl: 'https://www.heroeswm.ru',
            sellResUrl: 'sell_res.php',
            firstOpenProdUrl: '',
            workParams: {},
            statuses: {
                work: false,
                sellElements: false
            },
            resources: {
                'Золото':            { cost: 1,     minCount: 0, factoryTitle: null },
                'Древесина':         { cost: 180,   minCount: 5, factoryTitle: 'Лесопилка' },
                'Руда':              { cost: 180,   minCount: 5, factoryTitle: 'Рудник' },
                'Ртуть':             { cost: 360,   minCount: 3, factoryTitle: 'Лаборатория' },
                'Сера':              { cost: 360,   minCount: 3, factoryTitle: 'Залежи серы' },
                'Кристаллы':         { cost: 360,   minCount: 3, factoryTitle: 'Пещера кристаллов' },
                'Самоцветы':         { cost: 360,   minCount: 3, factoryTitle: 'Шахта самоцветов' },
                'Кожа':              { cost: 180,   minCount: 3, factoryTitle: 'Ферма' },
                'Мифриловая руда':   { cost: 460,   minCount: 3, factoryTitle: 'Мифриловая шахта' },
                'Обсидиан':          { cost: 2000,  minCount: 1, factoryTitle: 'Обсидиановая шахта' },
                'Волшебный порошок': { cost: 2074,  minCount: 1, factoryTitle: 'Фабрика магии' },
                'Мифрил':            { cost: 3325,  minCount: 1, factoryTitle: 'Литейный цех' },
                'Никель':            { cost: 1698,  minCount: 1, factoryTitle: 'Никелевый цех' },
                'Орихалк':           { cost: 11000, minCount: 1, factoryTitle: 'Плавильный цех' },
                'Сталь':             { cost: 759,   minCount: 2, factoryTitle: 'Сталелитейный цех' },
            },
            logDelimiter: '------------------------------',
            companies: {
                open: new Set(),
                unavailable: new Set()
            },
            intervalCounter: 0
        };

        var utils = {
            getDocFromString: function (response) {
                return new DOMParser().parseFromString(response, "text/html");
            },
            $ajax: function (method, url, params = {}) {
                return new Promise(function (resolve, reject) {
                    var xhr = new XMLHttpRequest();
                    xhr.onerror = reject;
                    //console.log(`I'm opening ${url}`);
                    xhr.open(method, url, true);
                    if (method.toLowerCase() === 'post') {
                        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                        xhr.onload = function () {
                            resolve(this.responseText);
                        };
                    } else if (method.toLowerCase() === 'get') {
                        var reader = new FileReader();
                        reader.addEventListener("loadend", function () {
                            resolve(reader.result);
                        });
                        xhr.responseType = "blob";
                        xhr.onload = function () {
                            reader.readAsText(xhr.response, "windows-1251");
                        };
                    }
                    xhr.send(params);
                });
            },
            log: function (data) {
                console.log(`${new Date().toLocaleString()}| ${data}`);
            },
            getCaptchaUrl: function (document) {
                return document.querySelector('img[name=imgcode]').getAttribute('src');
            },
            parseCaptcha: function (captchaUrl, serverUrl = globalVars.serverUrl) {
                var params = encodeURIComponent(captchaUrl);
                return this.$ajax('GET', `${serverUrl}/cap/${params}`);
            },
            sendCaptcha: function () {
                var workParams = globalVars.workParams;
                var params = this.stringifyParams(workParams);
                var url = `${globalVars.hwmUrl}/object_do.php`;
                utils.log(`Отправляю капчу по url: ${url}`, params);
                return this.$ajax('POST', url, params);
            },
            stringifyParams(params) {
                return Object
                  .keys(params)
                  .map((key) => `${key}=${params[key]}`)
                  .join('&')
                  ;
            },
            getWorkParams: function (doc, docStr) {
                var captchaInput = doc.querySelector('form[name="working"] input[type="text"]');
                utils.checkExistence(captchaInput, doc, 'Captcha input not found');

                var params = ['id', 'id2', 'idr', 'num', 'id3'].reduce((acc, curr) => {
                    const input = doc.querySelector(`input[name="${curr}"]`);
                    return {
                        ...acc,
                        [curr]: input && input.value,
                    }
                }, {});
                params.num = utils.getNumParamValue(docStr);

                return params;
            },
            getRandInt: function (min, max) {
                return Math.floor(Math.random() * (max - min + 1)) + min;
            },
            getFirstOpenFactoryUrl: function (doc) {
                var allLinks = [].filter.call(
                    doc.getElementsByTagName('a'),
                    (e) => e.innerHTML === '»»»'
                );
                if (allLinks.length > 0) {
                    var firstLink = allLinks[0];
                }
                return firstLink && firstLink.getAttribute('href');
            },
            getFactoriesOnMap: function (factoriesType = 'sh') {
                return utils.$ajax('GET', `https://www.heroeswm.ru/map.php?st=${factoriesType}`
                ).then((mapPage) => {
                    var doc = utils.getDocFromString(mapPage);
                    return doc.querySelectorAll('a[href*=object-info]:not([id])');
                });
            },
            parseFactories: function () {
                return Promise.all([
                    //parseFactoriesOnMap('mn'), // добыча не нужна для продажи ресурсов
                    utils.parseFactoriesOnMap('fc'),
                    utils.parseFactoriesOnMap('sh')
                ]);
            },
            parseFactoriesOnMap: function (type = 'sh') {
                return utils.getFactoriesOnMap(type).then((linkElems) => {
                    linkElems.forEach((linkElem) => {
                        var parent = linkElem.parentElement;
                        var color = parent.className;

                        var companies = globalVars.companies;
                        if (color === 'wbwhite') {
                            companies = companies.open;
                        } else if (color === 'wblight') {
                            companies = companies.unavailable;
                        } else {
                            companies = new Set();
                            console.log('Smth strange with color...');
                        }
                        var href = linkElem.getAttribute('href');
                        var companyId = +href.slice(href.lastIndexOf('=') + 1);
                        companies.add(companyId);
                    });
                });
            },
            findBestWork: function () { // TODO: REFACTORING
                var skip = false;
                var resultUrl = '';
                return getFactoriesOnMap('sh').then((url) => {
                    if (url) {
                        utils.log(`Самое выгодное - производство: ${url}`);
                        skip = true;
                        resultUrl = url;
                    } else {
                        utils.log(`Нет выгодных производств`);
                        return getFactoriesOnMap('fc');
                    }
                }).then((url) => {
                    if (skip) {
                        return;
                    }
                    if (url) {
                        utils.log(`Самое выгодное - обработка: ${url}`);
                        skip = true;
                        resultUrl = url;
                    } else {
                        utils.log(`Нет выгодных обработок`);
                        return getFactoriesOnMap('mn');
                    }
                }).then((url) => {
                    if (skip) {
                        return;
                    }
                    if (url) {
                        utils.log(`Самое выгодное - добыча: ${url}`);
                        resultUrl = url;
                    } else {
                        utils.log(`Очень странно, но нет свободных предприятий :/`);
                    }
                }).then(() => {
                    if (resultUrl) {
                        return utils.getFactoryPage(resultUrl.slice(resultUrl.lastIndexOf('=') + 1));
                    } else {
                        utils.log(`Что-то не так...`);
                    }
                }).then((factoryPage) => {
                    if (factoryPage && factoryPage.search(/Устройство на работу/i) !== -1) {
                        var factoryDocument = utils.getDocFromString(factoryPage);
                        globalVars.workParams = utils.getWorkParams(factoryDocument, factoryPage);
                    } else {
                        throw new Error('На производстве нет формы "Устройство на работу"');
                    }
                });

                function getFactoriesOnMap(type = 'sh') {
                    return utils.$ajax('GET', `https://www.heroeswm.ru/map.php?st=${type}`
                    ).then((mapPageFactories) => {
                        return onMapGetCallback(mapPageFactories);
                    });
                }

                /**
                 * Returns a Promise resolved with [url] OR [undefined]
                 */
                function onMapGetCallback(mapPageFactories) {
                    var doc = utils.getDocFromString(mapPageFactories);
                    var firstOpenProdUrl = utils.getFirstOpenFactoryUrl(doc);
                    if (firstOpenProdUrl) {
                        globalVars.firstOpenProdUrl = firstOpenProdUrl;
                    }

                    return new Promise(function (resolve) {
                        resolve(firstOpenProdUrl);
                    });
                }
            },
            getFactoryPage: function (factoryId) {
                return utils.$ajax('GET', `https://www.heroeswm.ru/object-info.php?id=${factoryId}`);
            },
            getCompanyParams: function (companyPage) {
                var doc = utils.getDocFromString(companyPage);

                return {
                    balance: getBalance(doc),
                    salary: getSalary(doc),
                    freePlaces: getFreePlaces(doc)
                };

                function getBalance(doc) {
                    var keyword = 'Баланс';
                    var balanceTextElem = [].filter.call(
                        doc.getElementsByTagName('td'),
                        (e) => e.innerText.slice(0, keyword.length) === keyword
                    )[0];

                    var balanceElem = balanceTextElem.nextSibling.querySelector('img[title="Золото"]').parentElement.nextSibling.firstElementChild;
                    var balance = parseInt(balanceElem.innerText.replace(/,/g, ''), 10);

                    return balance || null;
                }

                function getSalary(doc) {
                    var keyword = 'Зарплата';
                    var salaryTextElem = [].filter.call(
                        doc.getElementsByTagName('td'),
                        (e) => e.innerText.slice(0, keyword.length) === keyword
                    )[0];

                    var salaryElem = salaryTextElem.nextSibling.querySelector('img[title="Золото"]').parentElement.nextSibling.firstElementChild;
                    var salary = parseInt(salaryElem.innerText.replace(/,/g, ''), 10);

                    return salary || null;
                }

                function getFreePlaces(doc) {
                    var keyword = 'Свободных мест';
                    var freePlaces = [].filter.call(
                        doc.getElementsByTagName('b'),
                        (e) => e.previousSibling && e.previousSibling.textContent.slice(0, keyword.length) === keyword
                    )[0];
                    freePlaces = parseInt(freePlaces.innerText);

                    return freePlaces || null;
                }
            },
            getCharParams: function (charId = globalVars.charParams.id) {
                return utils.$ajax('GET', `https://www.heroeswm.ru/pl_info.php?id=${charId}`
                ).then((charPage) => {
                    var doc = utils.getDocFromString(charPage);
                    var wbs = doc.querySelectorAll('td.wb');
                    var paramsElem = wbs[1].querySelector('tr').children;
                    var paramsResources = wbs[10].getElementsByTagName('b');

                    var params = {};
                    for (var i = 0; i < paramsElem.length; i += 2) {
                        var elem = paramsElem[i].querySelector('img').getAttribute('title');
                        params[elem] = +paramsElem[i + 1]
                            .querySelector('b')
                            .innerText
                            .replace(/,/g, '');
                    }
                    [].forEach.call(paramsResources, (res) => {
                        params[res.innerText] = +res.nextSibling.textContent.replace(/: /g, '');
                    });

                    return params;
                });
            },
            getResourcesCostSum: function (resourcesObj = globalVars.resources) {
                var resources = globalVars.resources;
                return Object.keys(resourcesObj).reduce((acc, curr) => {
                    return acc + resourcesObj[curr].minCount * resources[curr].cost;
                }, 0);
            },
            getFactoriesTitles: (resources) => {
                return Object.keys(resources).reduce((accum, curr) => {
                    if (curr === 'Золото') return accum;
                    return accum[curr] = globalVars.resources[curr].factoryTitle, accum;
                }, {});
            },
            checkExistence: (item, dataAttachToError, errorMessage) => {
                if (!item) {
                    var e = new Error(errorMessage);
                    e.dataAttachToError = dataAttachToError;
                    throw e;
                }
            },
            logMoney: (params) => {
                utils.log(`Суммарно денег: ${Object.keys(params).reduce((accum, curr) => {
                    if (globalVars.resources[curr]) {
                        var cost = globalVars.resources[curr].cost;
                    }
                    cost = cost || 0;
                    return accum + params[curr] * cost;
                }, 0)}`);
            },
            getNumParamValue: (docStr) => {
                const s1 = `document.getElementById("num").value = `;
                const s2 = `; var l = document.getElementById("code").value.length`;
                const numValueExpression = docStr.slice(
                  docStr.indexOf(s1) + s1.length,
                  docStr.indexOf(s2),
                );
                return eval(numValueExpression);
            },
        };

        var game = {
            startSellElements: function () {
                if (globalVars.sellElementsInterval) {
                    game.stopSellElements();
                }
                utils.log(`Начинаю продавать элементы`);
                globalVars.statuses.sellElements = true;
                utils.parseFactories().then(() => {
                    globalVars.sellElementsInterval = setInterval(() => {
                        var companiesOpen = globalVars.companies.open;
                        var companiesUnavailable = globalVars.companies.unavailable;

                        companiesOpen.forEach((companyId) => {
                            //utils.log('Open company, sell: ' + companyId);
                            game.checkCompanyForSell(true, companyId);
                        });

                        if (globalVars.intervalCounter++ % 10 === 0) {
                            companiesUnavailable.forEach((companyId) => {
                                //utils.log('Unavailable company, sell: ' + companyId);
                                game.checkCompanyForSell(false, companyId);
                            });
                        }
                    }, 750);
                }).catch((e) => {
                    utils.log(`sellElementsLoop crashed:`);
                    console.log(e);
                });
            },
            checkCompanyForSell: function (isOpen, companyId) {
                return utils.$ajax('GET', `https://www.heroeswm.ru/object-info.php?id=${companyId}`
                ).then((companyPage) => {
                    var isCompanyInsolvent = (() => {
                        var companyParams = utils.getCompanyParams(companyPage);
                        return companyParams.balance > companyParams.salary && companyParams.freePlaces > 0;
                    })();

                    if (!isCompanyInsolvent && isOpen) {
                        utils.log(`Компания ${companyId} не готова к покупкам`);
                        globalVars.companies.open.delete(companyId);
                        globalVars.companies.unavailable.add(companyId);
                        return;
                    } else if (isCompanyInsolvent && !isOpen) {
                        utils.log(`Компания ${companyId} теперь готова к покупкам`);
                        globalVars.companies.unavailable.delete(companyId);
                        globalVars.companies.open.add(companyId);
                        return;
                    }
                    var doc = utils.getDocFromString(companyPage);
                    var forms = doc.querySelectorAll(`form[action="${globalVars.sellResUrl}"]`);
                    if (forms.length > 0) {
                        utils.log(`Успех! Можно продать ресурсы для компании ${companyId}`);
                        return Promise.all(
                            [].map.call(forms, game.sellResCallback)
                        ).then(() => {
                            return utils.getCharParams();
                        }).then((charParams) => {
                            utils.logMoney(charParams);
                        });
                    }
                });
            },
            sellResCallback: function (form) { // TODO: CHECK
                form.count.value = 99;
                var names = ['obj_id', 'check_code', 'res_id', 'count'];
                var formData = names.reduce((accum, curr) => {
                    var inputVal = form.querySelector(`input[name=${curr}]`).value;
                    return accum.concat(`${curr}=${encodeURIComponent(inputVal)}`);
                }, []).join('&');

                return utils.$ajax('POST', `/${globalVars.sellResUrl}`, formData);
            },
            stopSellElements: function () {
                globalVars.statuses.sellElements = false;
                utils.log(`Прекращаю продавать элементы`);
                clearInterval(globalVars.sellElementsInterval);
                delete globalVars.sellElementsInterval;
            },
            checkWorkStatus: function () {
                utils.log(`Проверка, может, я уже устроен?`);
                return utils.$ajax('GET', 'https://www.heroeswm.ru/home.php'
                ).then((charPage) => charPage.includes('Вы нигде не работаете.'));
            },
            getWork: function () {
                //game.stopSellElements();
                return game.checkWorkStatus().then((workStatus) => {
                    if (workStatus) {
                        utils.log(`Устраиваюсь на работу`);
                        return utils.$ajax('GET', 'https://www.heroeswm.ru/map.php?st=mn');
                    } else {
                        throw new Error('Уже устроен');
                    }
                }).then((mapPage) => { // открыть карту "Обработка"

                    var doc = utils.getDocFromString(mapPage);
                    var firstOpenProdUrl = utils.getFirstOpenFactoryUrl(doc);
                    if (firstOpenProdUrl) {
                        globalVars.firstOpenProdUrl = firstOpenProdUrl;
                        utils.log(`Первое открытое предприятие: ${firstOpenProdUrl}`);

                        return utils.$ajax('GET', `/${firstOpenProdUrl}`); // открыть ссылку первого открытого предприятия
                    } else {
                        throw new Error('Среди обработок нет открытых предприятий, crashed.');
                    }

                }).then((firstProdPage) => { // обработка страницы первого открытого предприятия

                    var doc = utils.getDocFromString(firstProdPage);
                    var captchaUrl = utils.getCaptchaUrl(doc); // получить относительную ссылку капчи
                    if (!captchaUrl) {
                        throw new Error('Captcha not found on page');
                    }
                    captchaUrl = `${globalVars.hwmUrl}/${captchaUrl}`; // абсолютная ссылка капчи
                    utils.log(`Ссылка на капчу: ${captchaUrl}, отправляю на локалхост`);

                    return utils.parseCaptcha(captchaUrl); // отправить капчу парситься на локалхост

                }).then((captchaText) => {  // после того, как капчу распарсили, передаю ее дальше;
                    // ищу максимально выгодное предприятие
                    utils.log(`Текст капчи: ${captchaText}`);
                    utils.log(`Ищу самое выгодное предприятие для устройства`);
                    return new Promise(function (resolve) {
                        return utils.findBestWork().then(() => {
                            resolve(captchaText);
                        });
                    });

                }).then((captchaText) => { // проверяю текст капчи и отправляю на сервер

                    if (captchaText.length !== 6) { // проверяю
                        throw new Error('Wrong captcha');
                    }
                    globalVars.workParams.code = captchaText;
                    //utils.GM_addData('hwm_workers_guild_log', `Get captcha: ${captchaText}`); // логаю

                    utils.log(`Составляю запрос и отправляю капчу на сервер`);
                    return utils.sendCaptcha(captchaText); // отправляю

                }).catch((e) => {
                    if (e.message === 'Уже устроен') {
                        return new Promise(function (resolve) {
                            resolve(e.message);
                        });
                    }
                    utils.log(`Ошибка в функции getWork`);
                    console.log(e);
                });
            },
            startGetWorkLoop: function () {
                game.getWork().then((afterCaptchaPage) => {
                    utils.log(`Ответ с сервера пришел`);
                    if (!afterCaptchaPage) {
                        throw new Error('There is no page after captcha input');
                    }
                    if (afterCaptchaPage.includes('Вы устроены на работу.')) {
                        var workDelay = (60 + utils.getRandInt(1, 15)) * 60000;
                        var nextWorkTime = new Date(+new Date() + workDelay);
                        setTimeout(game.startGetWorkLoop, workDelay);

                        utils.log(`${nextWorkTime} - время следующего устройства`);
                        console.log(globalVars.logDelimiter);
                    } else if (afterCaptchaPage.includes('Введен неправильный код.')) {
                        utils.log(`Введен неправильный код. Капча: ${globalVars.workParams.code}`);
                    } else if (afterCaptchaPage === 'Уже устроен') {
                        utils.log(`Да, я уже устроен`);
                        workDelay = 10 * 60000;
                        setTimeout(game.startGetWorkLoop, workDelay);
                    }
                });
            },
            startBuyElements: function () {
                setInterval(() => {
                    utils.getCharParams().then((charParams) => {
                        var toBuy = {};
                        var resources = globalVars.resources;
                        Object.keys(resources).forEach((res) => {
                            var resDiff = (charParams[res] || 0) - resources[res].minCount;
                            if (resDiff < 0) {
                                toBuy[res] = -1 * resDiff;
                            }
                        });
                        var totalCost = utils.getResourcesCostSum();
                        if (charParams['Золото'] >= totalCost) {
                            return game.buyResources(toBuy);
                        } else {
                            utils.log(`На закупку не хватает ${totalCost - charParams['Золото']}`);
                        }
                    });
                }, 5 * 1000);
            },
            getCharId: function () {
                return utils.$ajax('GET', `https://www.heroeswm.ru/home.php`
                ).then((homePage) => {
                    var doc = utils.getDocFromString(homePage);
                    var charLink = doc.querySelector('center > a.pi[href*="pl_info.php?id="]');
                    if (charLink) {
                        var href = charLink.getAttribute('href');
                        globalVars.charParams.id = href.slice(href.lastIndexOf('=') + 1);
                    } else {
                        var e = new Error('No char ID on homepage');
                        e.doc = doc;
                        throw e;
                    }
                });
            },
            buyResFromDoc: (doc, amount) => {
                var buyResForm = doc.querySelector('form[name="buy_res"]');
                utils.checkExistence(buyResForm, doc, 'No "buy_res" form on page');

                var amountAllowed;
                var howMuchCanIBuyElem = [].find.call(
                    buyResForm.querySelectorAll('td.wb[align="center"]'),
                    (td) => td.innerText.trim().includes('Можете купить:')
                ).querySelector('b');
                if (!howMuchCanIBuyElem) { // Не могу купить
                    amountAllowed = 0;
                    return;
                } else {
                    amountAllowed = +howMuchCanIBuyElem.innerText.replace(/,/g, '');
                }

                var flashParamsElem = buyResForm.querySelector('object > param[name="FlashVars"]');
                utils.checkExistence(flashParamsElem, doc, 'No "FlashVars" <param> on page');

                var buyResParams = flashParamsElem.getAttribute('value');
                utils.checkExistence(buyResParams, flashParamsElem, 'Empty value attr in flash <param>');
                buyResParams = buyResParams.split('|');

                buyResParams = {
                    //rand1: NaN,
                    pl_id: buyResParams[7],
                    obj_id: buyResParams[5],
                    check_code: buyResParams[6],
                    count: amount
                };
                var POST_query = Object.keys(buyResParams).reduce((accum, curr) => {
                    return accum + `&${curr}=${buyResParams[curr]}`;
                }, `rand1=NaN`);

                if (amountAllowed >= amount) {
                    return utils.$ajax('POST', 'https://www.heroeswm.ru/buy_res.php', POST_query);
                }
            },
            buyResOnMap: function (factoryLink, amount) {
                return utils.$ajax('GET', factoryLink).then((factoryPage) => {
                    var doc = utils.getDocFromString(factoryPage);
                    return game.buyResFromDoc(doc, amount);
                });
            },
            buyResources: function (toBuy) {
                var factoriesThatINeed = utils.getFactoriesTitles(toBuy);
                var factoriesParsed = {};

                function updateFactories(linkElems) {
                    linkElems.forEach((a) => {
                        var resKey = Object.keys(factoriesThatINeed).filter((key) => {
                            return factoriesThatINeed[key] === a.innerText;
                        })[0];

                        if (resKey) {
                            factoriesParsed[resKey] = {
                                factoryTitle: a.innerText,
                                link: a.getAttribute('href')
                            };
                        }
                    });
                }

                return utils.getFactoriesOnMap('mn').then((linkElems) => { // ДОБЫЧА
                    updateFactories(linkElems);

                    return utils.getFactoriesOnMap('fc'); // ОБРАБОТКА
                }).then((linkElems) => {
                    updateFactories(linkElems);

                }).then(() => {
                    return Promise.all(Object.keys(factoriesParsed).map((res) => {
                        utils.log(`Покупаю ${toBuy[res]} шт. "${res}" на предприятии `);
                        return game.buyResOnMap(factoriesParsed[res].link, toBuy[res]);
                    }));
                });
            },
        };

        // var regexPattern = /Район:[\s\S]*?<a[\s\S]*?>[\s]{2}([\s\S]+?)<\/a>/i;
        // result = response.match(regexPattern)[1]; // <--- RETURN THIS

        var getOptionsElem = () => {
            var existentElem = document.querySelector('.bot-options');
            if (existentElem) {
                return existentElem;
            }

            var wrapper = document.createElement('div');
            wrapper.className = 'bot-options';

            var sellButton = (() => {
                var sellButton = document.createElement('button');
                sellButton.id = 'sellButton';
                sellButton.addEventListener('click', function () {
                    var status = globalVars.statuses.sellElements;
                    if (status) {
                        game.stopSellElements();
                    } else {
                        game.startSellElements();
                    }
                    updateOptions();
                });
                return sellButton;
            })();

            var workButton = (() => {
                var workButton = document.createElement('button');
                workButton.id = 'workButton';
                workButton.disabled = true;
                return workButton;
            })();

            wrapper.appendChild(sellButton);
            wrapper.appendChild(workButton);

            var s = wrapper.style;
            s.position = 'fixed';
            s.left = '20px';
            s.top = '20px';

            return wrapper;
        };

        function updateOptions() {
            document.getElementById('sellButton').innerText = `Продавать элементы: ${globalVars.statuses.sellElements}`;
            document.getElementById('workButton').innerText = `Устроен на работу: ${globalVars.statuses.work}`;
        }

        function showOnlyOptions() {
            document.querySelector('table').hidden = true;
            document.querySelector('center').hidden = true;
            document.body.appendChild(getOptionsElem());
        }

        function init() {
            showOnlyOptions();
            myBot.getCharId().then(() => {
                myBot.work();
                myBot.buyStart();
                myBot.sellStart();
                updateOptions();
            });
        }

        return {
            work: game.startGetWorkLoop,
            sellStart: game.startSellElements,
            buyStart: game.startBuyElements,
            sellStop: game.stopSellElements,
            getCharId: game.getCharId,
            init
        };
    })();

    myBot.init();
    setTimeout(() => {
        location.reload();
    }, 5 * 60 * 1000);
})();