Lolzteam Multiaccount Finder

Your assistant in finding scammers on the forum

目前為 2023-08-29 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Lolzteam Multiaccount Finder
// @version      1.9.3
// @description  Your assistant in finding scammers on the forum
// @author       vuchaev2015
// @match        https://zelenka.guru/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=zelenka.guru
// @grant GM_setValue
// @grant GM_getValue
// @grant GM.setValue
// @grant GM.getValue
// @namespace http://tampermonkey.net/
// ==/UserScript==

// ВНИМАНИЕ ДАННЫЙ СКРИПТ СОДЕРЖИТ БОЛЬШОЕ КОЛИЧЕСТВО ГАВНОКОДА
// ПОЖАЛУЙСТА, НЕ БЕЙТЕ. ГЛАВНОЕ, ЧТО ВСЁ РАБОТАЕТ!.

let domain = 'zelenka.guru';
let items = [
    {key: "autocheck-mini-profile", value: "false"},
    {key: "autocheck-profile", value: "false"},
    {key: "autocheck-banned-users-mporp", value: "false"},
    {key: "addbutton-profile", value: "true"},
    {key: "addbutton-threads", value: "true"},
    {key: "autocheck-online-registered", value: "false"},
    {key: "show-blocked-percentage", value: "true"},
    {key: "show-unblocked-percentage", value: "true"},
    {key: "show-total-users-ip", value: "true"},
    {key: "show-blocked-this-month-percentage", value: "true"},
    {key: "autocheck-newmembers", value: "false"},
    {key: "autocheck-only-parameters", value: "false"},
    {key: "autocheck-only-parameters-sympathies", value: "20"},
    {key: "autocheck-only-parameters-messages", value: "50"},
    {key: "addbutton-chat", value: "true"},
    {key: "addbutton-alerts", value: "true"},
    {key: "addbutton-conversations", value: "true"},
    {key: "retry-after-error", value: "true"},
    {key: "fast-switch-with-button", value: "false"},
    {key: "fast-switch-with-button-key", value: 'F2'},
    {key: "switch-page-automatically", value: false},
    {key:"checked-list",value:[]}
];

async function addItem(item) {
    let currentValue = await checkKeyValue(item.key);
    if (currentValue === undefined) {
        GM_setValue(item.key, item.value);
    }
}


function changeItemValue(key, value) {
    console.log(key, value)
    GM_setValue(key, value);
}

function addItems(items) {
    items.forEach(item => addItem(item));
}

function checkKeyValue(key) {
    return Promise.resolve(GM_getValue(key));
}

addItems(items);

let accountMenu = document.getElementById("AccountMenu");
let linksList = accountMenu.querySelector(".blockLinksList");
let buttonId = `lmfsettings`;

linksList.insertAdjacentHTML('beforeend', `<li><a href="javascript:void(0)" id="${buttonId}">Multiaccount Finder</a></li>`);

document.getElementById(buttonId).addEventListener("click", function (event) {
    event.preventDefault();
    openSettings();
});

let hrefSearchUsers = document.querySelector('a[href^="/search/search?users="]').href.split('?users=')[1].split('&')[0];
let profileLink = document.querySelector("#AccountMenu > ul > li:nth-child(1) > a").getAttribute("href").split(`${domain}`)[1];

const months = ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'];
const date = new Date();
const month = months[date.getMonth()];

async function renderCheckboxes(checkboxes, page, lastId) {
    const numCheckboxes = checkboxes.length;
    const checkboxesPerPage = 10;
    const numPages = Math.ceil(numCheckboxes / checkboxesPerPage);
    const startIndex = (page - 1) * checkboxesPerPage;
    const endIndex = page * checkboxesPerPage;
    filteredCheckboxes = checkboxes.slice(startIndex, endIndex);
    let nextPage = page + 1;
    let prevPage = page - 1;
    let content = "";
    const promises = filteredCheckboxes.map(async (checkbox) => {
        let isChecked = await checkKeyValue(checkbox.id) === "true";
        const disabled = checkbox.dependent && !checkbox.dependent.every(async function (dep) {
            return await checkKeyValue(dep) === "true";
        });
        return '<div> <input type="checkbox" id="' + checkbox.id + '-' + lastId + '" name="' + checkbox.id + '-' + lastId + '" ' + (isChecked ? 'checked="checked" ' : '') + (disabled ? 'disabled ' : '') + 'value="1"> ' + checkbox.label + '</div>';
    });
    const results = await Promise.all(promises);
    content = results.join('<br>');

    function renderPage(content) {
        function addPreviousPageButton() {
            if (prevPage >= 1) {
                content += '<br>';
                content += (nextPage <= numPages) ? '<div style="margin-right: 10px; display: inline-block;"><button type="button" name="prev" value="Предыдущая страница" accesskey="s" class="button primary" id="prev-page-' + lastId + '">Предыдущая страница</button></div>' : '<button type="button" name="prev" value="Предыдущая страница" accesskey="s" class="button primary" id="prev-page-' + lastId + '">Предыдущая страница</button>';
            }
        }

        function addNextPageButton() {
            if (nextPage <= numPages) {
                content += (prevPage >= 1) ? '<button type="button" name="next" value="Следующая страница" accesskey="s" class="button primary" id="next-page-' + lastId + '">Следующая страница</button>' : '<br><button type="button" name="next" value="Следующая страница" accesskey="s" class="button primary" id="next-page-' + lastId + '">Следующая страница</button>';
            }
        }

        function addPageNumber() {
            content += '<span style="margin-left: 10px;">Страница: ' + page + ' из ' + numPages + '</span>';
        }
        addPreviousPageButton();
        addNextPageButton();
        addPageNumber()
        return content
    }
    content = await renderPage(content);
    return content
}

let filteredCheckboxes

async function openSettings(page = 1) {
    let modals = document.querySelectorAll('div.modal.fade');
    let lastModal = modals[modals.length - 1];
    if (lastModal && lastModal.querySelector('[id^="addbutton-"]')) {
        lastModal.remove();
    }

    document.querySelectorAll('div.modal-backdrop').forEach(modalBackdrop => modalBackdrop.remove());

    const lastId = generateRandomString(10);

    let checkboxes = [
        { id: 'autocheck-profile', label: 'Автоматическая проверка в профиле' },
        { id: 'autocheck-mini-profile', label: 'Автоматическая проверка в мини-профиле' },
        { id: 'autocheck-banned-users-mporp', label: 'Автоматическая проверка для заблокированных', dependent: ['autocheck-profile', 'autocheck-mini-profile'] },
        { id: 'autocheck-newmembers', label: 'Автоматическая проверка новых пользователей в разделе /members' },
        { id: 'autocheck-online-registered', label: 'Автоматическая проверка в разделе /online/?type=registered' },
        { id: 'autocheck-only-parameters', label: `Автоматическая проверка только по параметрам (<span id="sympCount-${lastId}">${await checkKeyValue('autocheck-only-parameters-sympathies')}</span> симпатий и <span id="msgCount-${lastId}">${await checkKeyValue('autocheck-only-parameters-messages')}</span> сообщений)` },
        { id: 'addbutton-threads', label: 'Кнопка на посты и комментарии в теме (три точки)' },
        { id: 'addbutton-chat', label: 'Кнопка на сообщения в чате (три точки)' },
        { id: 'addbutton-profile', label: 'Кнопка на посты и комментарии в профиле (три точки)' },
        { id: 'addbutton-alerts', label: 'Кнопка на уведомления (три точки)' },
        { id: 'addbutton-conversations', label: 'Кнопка на диалоги в личных сообщениях (три точки)' },
        { id: 'show-blocked-percentage', label: 'Отображать в подробной информации % заблокированных' },
        { id: 'show-unblocked-percentage', label: 'Отображать в подробной информации % не заблокированных' },
        { id: 'show-total-users-ip', label: 'Отображать в подробной информации общее количество пользователей в общих IP' },
        { id: 'show-blocked-this-month-percentage', label: 'Отображать в подробной информации % от заблокированных в этом месяце' },
        { id: 'fast-switch-with-button', label: `Быстрое переключение на следующую страницу кнопкой <span id="buttonkey-${lastId}">${await checkKeyValue('fast-switch-with-button-key')}</span>` },
        { id: 'retry-after-error', label: 'Повторная проверка после ошибки Name not found (15000 ms)' },
        { id: 'switch-page-automatically', label: 'Переключать на следующую страницу автоматически (пока не найдет мошенника)' },
        { id: 'not-to-check-previously-checked', label: `Не выполнять повторную проверку если пользователь ранее проверялся (<span id="clear-database-${lastId}">Нажмите здесь, чтобы очистить базу данных</span>)` }]

    let content = await renderCheckboxes(checkboxes, page, lastId);

    XenForo.alert(content, 'Lolzteam Multiaccount Finder');

    filteredCheckboxes.forEach(function(checkbox, index) {
        const id = checkbox.id + '-' + lastId;
        const checkboxEl = document.getElementById(id);
        if (checkboxEl) {
            checkboxEl.onclick = function() {
                changeItemValue(checkbox.id, `${this.checked}`);
                console.log(`Checkbox ${checkbox.id} is now ${this.checked}`);
            }
        }
    });

    const prevButton = document.getElementById("prev-page-" + lastId);
    const nextButton = document.getElementById("next-page-" + lastId);

    if (prevButton) {
        prevButton?.addEventListener("click", openSettings.bind(null, page - 1));
    }
    if (nextButton) {
        nextButton?.addEventListener("click", openSettings.bind(null, page + 1));
    }

    const addClickListener = (selector, promptMessage, localStorageKey, callback) => {
        const el = document.querySelector(selector);
        if (el) {
            el.addEventListener('click', () => {
                if (callback) {
                    callback();
                } else {
                    const newValue = prompt(promptMessage);
                    if (newValue !== null && !isNaN(parseInt(newValue)) && newValue.trim() !== '') {
                        changeItemValue(localStorageKey, newValue);
                        el.textContent = newValue;
                    }
                }
            });
        }
    };

    addClickListener(`#clear-database-${lastId}`, null, null, () => {
        if (confirm("Вы уверены, что хотите очистить базу данных?")) {
            changeItemValue("checked-list", []);
            alert('База данных очищена');
        }
    });

    addClickListener(`#sympCount-${lastId}`, "Введите новое значение счетчика симпатий:", "autocheck-only-parameters-sympathies");
    addClickListener(`#msgCount-${lastId}`, "Введите новое значение счетчика сообщений:", "autocheck-only-parameters-messages");

    const buttonKey = document.querySelector(`#buttonkey-${lastId}`);
    if (buttonKey) {
        let keydownListener;
        buttonKey.addEventListener('click', () => {
            buttonKey.style.color = 'red';
            const toggleKeydownListener = () => {
                if (keydownListener) {
                    document.removeEventListener('keydown', keydownListener);
                    buttonKey.style.color = '';
                    keydownListener = null;
                } else {
                    const currentKey = checkKeyValue('fast-switch-with-button-key');
                    keydownListener = (event) => {
                        if (event.key !== currentKey) {
                            changeItemValue('fast-switch-with-button-key', event.key);
                            buttonKey.textContent = event.key;
                            buttonKey.style.color = '';
                            document.removeEventListener('keydown', keydownListener);
                            keydownListener = null;
                        }
                    };
                    document.addEventListener('keydown', keydownListener);
                }
            };
            toggleKeydownListener();
        });
    }
}

async function checkMenuItems() {
    const sharedItems = document.querySelectorAll('.Menu a[href*="/shared-ips"]');
    for (let i = 0; i < sharedItems.length; i++) {
        const item = sharedItems[i];
        const menu = item.parentNode.parentNode;
        if (menu.hasAttribute("data-multiaccount-finder")) continue;
        menu.setAttribute("data-multiaccount-finder", "added");
        const buttonId = `multiaccountFinderButton-${generateRandomString(10)}`;
        const currentUrl = item.getAttribute('href');
        menu.appendChild(createButtonElement(buttonId, currentUrl));
        const makeClaimLink = menu.querySelector('a[href*="/make-claim"]');
        if (makeClaimLink) {
            if (await checkKeyValue("autocheck-mini-profile") !== 'true') continue;
            const bannedModule = document.querySelectorAll('.usernameAndStatus');
            for (let j = 0; j < bannedModule.length; j++) {
                const module = bannedModule[j];
                const bannedcheck = module.parentNode.parentNode;
                if (bannedcheck.hasAttribute("data-multiaccount-finder")) continue;
                bannedcheck.setAttribute("data-multiaccount-finder", "added");
                const gifId = `gif-profile-${generateRandomString(10)}`;
                const countsModule = document.querySelectorAll('.userStatCounters');
                let lastElement = countsModule[countsModule.length - 1]
                const miniprofileMenu = lastElement.parentNode.parentNode;
                if (miniprofileMenu.hasAttribute("data-multiaccount-finder")) continue;
                miniprofileMenu.setAttribute("data-multiaccount-finder", "added");
                let sympathies = lastElement.querySelector('a:nth-child(1) > span.count').textContent.replace(/ /g, "");
                console.log(sympathies)
                let messages = lastElement.querySelector('a:nth-child(2) > span.count').textContent.replace(/ /g, "");
                console.log(messages)
                if (sympathies || messages) {
                    if (await checkKeyValue("autocheck-only-parameters") === 'true' && (sympathies >= parseInt(await checkKeyValue("autocheck-only-parameters-sympathies")) && messages >= parseInt(await checkKeyValue("autocheck-only-parameters-messages")))) continue;
                }
                lastElement.appendChild(createGifElement(gifId, 'https://i.imgur.com/I5VH0zp.gif', 24, 24));
                if (await checkKeyValue("autocheck-banned-users-mporp") === 'false' && bannedcheck.querySelector('.banInfo.muted.Tooltip') || bannedcheck.querySelector('div.errorPanel')) {
                    const element = document.getElementById(gifId);
                    if (element) element.remove();
                    continue;
                }
                const element = document.getElementById(buttonId);
                if (element) element.remove();
                checkUser(currentUrl, undefined, gifId).then();
            }
        } else {
            if (await checkKeyValue("autocheck-profile") !== 'true') return;
            let sympathies = document.querySelector("#content > div > div > div.profilePage > div.mainProfileColumn > div > div.counts_module > a.page_counter.Tooltip > div.count").textContent.replace(/ /g, "");
            console.log(sympathies)
            let messages = document.querySelector("#content > div > div > div.profilePage > div.mainProfileColumn > div > div.counts_module > a:nth-child(3) > div.count").textContent.replace(/ /g, "");
            console.log(messages)
            if (await checkKeyValue("autocheck-only-parameters") === 'true' && document.querySelector("#content > div > div > div.profilePage > div.mainProfileColumn > div > div.counts_module > a.page_counter.Tooltip > div.count") && document.querySelector("#content > div > div > div.profilePage > div.mainProfileColumn > div > div.counts_module > a:nth-child(3) > div.count") && (sympathies >= parseInt(await checkKeyValue("autocheck-only-parameters-sympathies")) && messages >= parseInt(await checkKeyValue("autocheck-only-parameters-messages")))) return;
            const bannedModule = document.querySelectorAll('div.mainProfileColumn');
            for (let i = 0; i < bannedModule.length; i++) {
                const bannedcheck = bannedModule[i].parentNode.parentNode;
                if (bannedcheck.hasAttribute("data-multiaccount-finder")) continue;
                bannedcheck.setAttribute("data-multiaccount-finder", "added");
                const gifId = `gif-profile`;
                const countsModule = document.querySelectorAll('.counts_module');
                for (let j = 0; j < countsModule.length; j++) {
                    const profilecounter = countsModule[j].parentNode.parentNode;
                    if (profilecounter.hasAttribute("data-multiaccount-finder")) continue;
                    profilecounter.setAttribute("data-multiaccount-finder", "added");
                    if (sympathies || !messages) {
                        if (await checkKeyValue("autocheck-only-parameters") === 'true' && (sympathies >= parseInt(await checkKeyValue("autocheck-only-parameters-sympathies")) && messages >= parseInt(await checkKeyValue("autocheck-only-parameters-messages")))) return;
                    }
                    countsModule[j].appendChild(createGifElement(gifId, 'https://i.imgur.com/I5VH0zp.gif', 32, 32));
                    if (await checkKeyValue("autocheck-banned-users-mporp") === 'false' && bannedcheck.querySelector('div.errorPanel')) {
                        const element = document.getElementById(gifId);
                        if (element) element.remove();
                        return;
                    }
                    const element = document.getElementById(buttonId);
                    if (element) element.remove();
                    checkUser(currentUrl, undefined, gifId).then();
                }}}}}

function createButtonElement(buttonId, currentUrl) {
    const multiaccountFinderItem = document.createElement("li");
    const button = document.createElement("a");
    button.setAttribute("href", "javascript:void(0)");
    button.setAttribute("id", buttonId);
    button.textContent = "Multiaccount Finder";
    button.addEventListener("click", function(event) {
        event.preventDefault();
        checkUser(`https://${domain}/${currentUrl}/shared-ips/`).then();
    });
    multiaccountFinderItem.appendChild(button);
    return multiaccountFinderItem;
}

function createGifElement(gifId, src, width, height) {
    const gifElement = document.createElement('img');
    gifElement.id = gifId;
    gifElement.src = src;
    gifElement.width = width;
    gifElement.height = height;
    return gifElement;
}

function generateRandomString(length) {
    let result = '';
    let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let charactersLength = characters.length;
    for (let i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}

async function checkThreadItems() {
    if (await checkKeyValue("addbutton-threads") === 'true') {
        const linksLists = [...document.querySelectorAll('.secondaryContent.blockLinksList')]
        .filter(list => !list.querySelector('li[id^="multiaccountFinderButton-"]'));

        linksLists.forEach((linksList) => {
            const links = linksList.querySelectorAll("a");

            links.forEach((link) => {
                if (link.href.startsWith(`https://${domain}/posts/`)) {
                    let postId;
                    let newLink;
                    let postElement;

                    if (link.href.includes('posts/comments/')) {
                        postId = link.href.split('posts/comments/')[1].split('/')[0];
                        newLink = `post-comment-${postId}`
                    } else {
                        postId = link.href.split('posts/')[1].split('/')[0];
                        newLink = `post-${postId}`
                    }

                    postElement = document.querySelector(`#${newLink}.${link.href.includes('posts/comments/') ? 'comment' : 'message'}`);

                    if (postElement && !postElement.hasAttribute("data-multiaccount-finder")) {
                        postElement.setAttribute("data-multiaccount-finder", "added");

                        const menus = [...document.querySelectorAll('div.Menu')]
                        .filter(menu => [...menu.querySelectorAll('a')].some(link => link.href.includes(`${postId}`)));

                        const author = postElement.querySelector('.username').textContent;
                        if (author !== hrefSearchUsers) {
                            const buttonId = `multiaccountFinderButton-${generateRandomString(10)}`;

                            const usernameLink = postElement.querySelector('a');
                            const currentUrl = usernameLink.getAttribute('href');

                            menus[menus.length - 1].querySelector('.secondaryContent').appendChild(createButtonElement(buttonId, currentUrl));
                        }
                    }
                }
            });
        });
    }
}

async function checkProfileItems() {
    const profilePostList = document.querySelector('ol#ProfilePostList');
    if (((await checkKeyValue("addbutton-profile")) === 'true') && profilePostList) {
        const linksLists = [...profilePostList.querySelectorAll(':not(li[id^="multiaccountFinderButton-"])')];
        linksLists.forEach((linksList) => {
            const links = linksList.querySelectorAll("a");
            links.forEach((link) => {
                if (link.href.startsWith(`https://${domain}/profile-posts/`)) {
                    let postId;
                    let newLink;
                    let postElement;
                    if (link.href.includes('profile-posts/comments')) {
                        postId = link.href.split('posts/comments/')[1].split('/')[0];
                        newLink = `profile-post-comment-${postId}`
                        postElement = document.querySelector(`#${newLink}.comment`);
                    } else if (!link.href.includes('profile-posts/comments/')) {
                        postId = link.href.split('profile-posts/')[1].split('/')[0];
                        newLink = `profile-post-${postId}`
                        postElement = document.querySelector(`#${newLink}.messageSimple`);
                    }
                    if (postElement && !postElement.hasAttribute("data-multiaccount-finder")) {
                        postElement.setAttribute("data-multiaccount-finder", "added");
                        const menus = [...document.querySelectorAll('div.Menu')].filter(menu => [...menu.querySelectorAll('a')].some(link => link.href.includes(`${postId}`)));
                        let author = postElement.querySelector('a.username.poster')
                        if (author.textContent !== hrefSearchUsers) {
                            document.createElement("li");
                            let buttonId = `multiaccountFinderButton-${generateRandomString(10)}`;
                            let currentUrl = author.getAttribute('href')
                            console.log(menus[menus.length - 1])
                            if (menus.length > 0) {
                                menus[menus.length - 1].querySelector('.secondaryContent').appendChild(createButtonElement(buttonId, currentUrl));
                            }
                        }
                    }
                }
            })
        })
    }
}



async function checkAlertItems() {
    if ((await checkKeyValue("addbutton-alerts")) === 'true') {
        const alertElements = document.querySelectorAll('li.Alert');
        alertElements.forEach((alertElement) => {
            if (alertElement.querySelector('a[rel="menu"].PopupControl.dottesStyle.PopupContainerControl.PopupOpen')) {
                if (alertElement && !alertElement.hasAttribute("data-multiaccount-finder")) {
                    const username = alertElement.querySelector('a.username')
                    let menus = document.querySelectorAll('.Menu.MenuOpened');
                    if (!username && !menus) return;
                    const usernameLink = username.getAttribute('href');
                    const lastMenu = menus[menus.length - 1];
                    let buttonId = `multiaccountFinderButton-${generateRandomString(10)}`;
                    lastMenu.querySelector('ul.secondaryContent.blockLinksList').appendChild(createButtonElement(buttonId, usernameLink));
                    alertElement.setAttribute("data-multiaccount-finder", "added");
                }
            }
        })
    }
}

async function checkConversationItems() {
    if ((await checkKeyValue("addbutton-conversations")) === 'true') {
        if (!window.location.href.startsWith(`https://${domain}/conversations/`)) return
        const username = document.querySelector('div.ImDialogHeader a.username');
        if (!username) return
        const usernameLink = username.getAttribute('href');
        const menuElements = Array.from(document.querySelectorAll('div.Menu')).filter(menuElement => menuElement.querySelector('.blockLinksList a[href^="conversations/"]'));
        const targetElement = menuElements[menuElements.length - 1];
        if (targetElement && !targetElement.hasAttribute("data-multiaccount-finder")) {
            document.createElement("li");
            let buttonId = `multiaccountFinderButton-${generateRandomString(10)}`;
            targetElement.querySelector('.blockLinksList').appendChild(createButtonElement(buttonId, usernameLink));
            targetElement.setAttribute("data-multiaccount-finder", "added");
        }
    }
}

function update() {
    checkMenuItems();
    checkThreadItems();
    checkProfileItems();
    checkChatItems();
    checkAlertItems();
    checkConversationItems();

    requestAnimationFrame(update);
}

requestAnimationFrame(update);

function checkChatItems() {
    if (localStorage.getItem("addbutton-chat") !== 'true') return;
    const elements = document.querySelectorAll('div[class^="chat2-message-block "]');
    elements.forEach((message, index) => {
        let usernameLink;
        const lztui = document.querySelectorAll('div[class^="lztui-Popup lztng-"]');
        const lastElement = lztui[lztui.length - 1];
        const popupElement = message.querySelector('div[class^="PopupControl PopupOpen"]');
        if (!popupElement) return;

        if (message) {
            usernameLink = message.querySelector('.username[href]');
            usernameLink = usernameLink && usernameLink.href.includes(profileLink) ? null : usernameLink;
            if (!usernameLink) {
                let prevIndex = index - 1;
                while (prevIndex >= 0 && !usernameLink) {
                    const prevMessage = elements[prevIndex];
                    usernameLink = prevMessage.querySelector('.username[href]');
                    prevIndex--;
                }
            }
            const ulElement = lastElement.querySelector('ul.secondaryContent.blockLinksList');
            if (!ulElement || ulElement.hasAttribute("data-multiaccount-finder")) return;

            ulElement.setAttribute("data-multiaccount-finder", "added");
            const username = usernameLink.textContent
            const buttonId = `multiaccountFinderButton-${generateRandomString(10)}`;
            if (username !== hrefSearchUsers) {
                ulElement.appendChild(createButtonElement(buttonId, usernameLink.href.replace(`https://${domain}`, '')));
            }
        }
    });
}

async function OnlineChangeTable(classname, num) {
    const findelement = document.querySelector(`${classname}`);
    const remainedElement = document.querySelector('.remained dd');
    if (findelement) {
        const ddElement = findelement.querySelector('dd');
        if (ddElement) {
            const currentValue = parseInt(ddElement.textContent);
            ddElement.textContent = currentValue + num;
            if (findelement.classList.contains('scammers')) {
                ddElement.style.color = 'red';
            }
        }
    }
    const shouldDecrementRemainedElement = !(classname === 'dl.errors' && await checkKeyValue('retry-after-error') === 'true');
    if (remainedElement && shouldDecrementRemainedElement) {
        const currentValueRemained = parseInt(remainedElement.textContent);
        remainedElement.textContent = currentValueRemained - 1;
    }
}

async function AutoCheckOnlineRegistered() {
    if ((await checkKeyValue("autocheck-online-registered")) === 'true') {
        if (window.location.href.indexOf(`https://${domain}/online/?type=registered`) === 0) {
            const currentPage = parseInt(document.querySelector('.currentPage').innerText.trim());
            const maxPage = parseInt(document.querySelector("#content > div > div > div > div > div > div > nav > a:nth-child(5)").innerText.trim());

            if (await checkKeyValue("fast-switch-with-button") === 'true') {
                let fastswitchwithbuttonkey = await checkKeyValue("fast-switch-with-button-key");
                document.addEventListener('keydown', function(event) {
                    if (event.key === fastswitchwithbuttonkey && currentPage < maxPage) {
                        window.location.href = `https://${domain}/online/?type=registered&page=${currentPage + 1}`;
                    }
                });
            }

            const visitorCountDl = document.querySelector('dl.visitorCount');
            const members = document.querySelectorAll('.member');
            if (visitorCountDl && !visitorCountDl.querySelector('dl.clean')) {
                const newFootnoteDiv = document.createElement('div');
                newFootnoteDiv.className = 'footnote';
                newFootnoteDiv.innerHTML = `<h3>Lolzteam Multiaccount Finder</h3><dl class="clean"><dt>Не заподозрены:</dt><dd>0</dd></dl><dl class="vpn"><dt>VPN:</dt><dd>0</dd></dl><dl class="scammers"><dt>Мошенники:</dt><dd>0</dd></dl><dl class="errors"><dt>Ошибки:</dt><dd>0</dd>${await checkKeyValue("autocheck-only-parameters") === "true" ? `<dl class="skipped"><dt>Не подошли под указанные параметры:</dt><dd>0</dd></dl>` : ''}${await checkKeyValue("not-to-check-previously-checked") === "true" ? `<dl class="checked"><dt>Ранее проверялись:</dt><dd>0</dd></dl>` : ''}<dl class="remained"><dt>Осталось проверить:</dt><dd>${members.length}</dd></dl>`;
                visitorCountDl.appendChild(newFootnoteDiv);
            }

            let index = 0;
            const checkNextMember = async () => {
                if (index >= members.length) {
                    const scammersCount = parseInt(document.querySelector("dl.scammers dd").innerText);
                    if (await checkKeyValue("switch-page-automatically") === 'true' && currentPage < maxPage && scammersCount < 1) {
                        window.location.href = `https://${domain}/online/?type=registered&page=${currentPage + 1}`;
                    } else if (scammersCount > 0) { document.title = 'Обнаружен мошенник' } return;
                }

                const member = members[index];
                const usernameLink = member.querySelector('a.username');
                const usernameHref = usernameLink.getAttribute('href');
                const userStatCounters = member.querySelector('.userStatCounters');

                const gifId = `gif-${index}`;

                if (usernameLink.textContent !== hrefSearchUsers) {
                    const sympathies = member.querySelector("div.userStatCounters > div:nth-child(1) > span.count").textContent.replace(/ /g, "")
                    const messages = member.querySelector("div.userStatCounters > div:nth-child(2) > span.count").textContent.replace(/ /g, "")

                    if (await checkKeyValue("autocheck-only-parameters") === "true") {
                        if ((sympathies < parseInt(await checkKeyValue("autocheck-only-parameters-sympathies")) && messages < parseInt(await checkKeyValue("autocheck-only-parameters-messages")))
                            || (sympathies >= parseInt(await checkKeyValue("autocheck-only-parameters-sympathies")) && messages < parseInt(await checkKeyValue("autocheck-only-parameters-messages")))
                            || (sympathies < parseInt(await checkKeyValue("autocheck-only-parameters-sympathies")) && messages >= parseInt(await checkKeyValue("autocheck-only-parameters-messages")))) {
                            userStatCounters.appendChild(createGifElement(gifId, 'https://i.imgur.com/I5VH0zp.gif', 24,24));
                            await checkUser(`https://${domain}/${usernameHref}shared-ips`, 'registered', gifId);
                        } else {
                            OnlineChangeTable('dl.skipped', 1)
                        }
                    } else {
                        userStatCounters.appendChild(createGifElement(gifId, 'https://i.imgur.com/I5VH0zp.gif', 24,24));
                        await checkUser(`https://${domain}/${usernameHref}shared-ips`, 'registered', gifId);
                    }
                } else {
                    OnlineChangeTable('dl.skipped', 0)
                }
                index++;
                await checkNextMember();
            }

            checkNextMember().then();
        }
    }
}

AutoCheckOnlineRegistered()

async function AutoCheckNewMembers() {
    if ((await checkKeyValue("autocheck-newmembers")) === 'true') {
        if (window.location.href.indexOf(`https://zelenka.guru/members`) === 0) {
            const visitorCountDl = document.querySelector('dl.memberCount')
            const members = document.querySelectorAll('.secondaryContent.avatarHeap.avatarList li')

            if (visitorCountDl && !visitorCountDl.querySelector('dl.clean')) {
                const newFootnoteDiv = document.createElement('div')
                newFootnoteDiv.className = 'footnote'
                newFootnoteDiv.innerHTML = `<h3>Lolzteam Multiaccount Finder</h3><dl class="clean"><dt>Не заподозрены:</dt><dd>0</dd></dl><dl class="vpn"><dt>VPN:</dt><dd>0</dd></dl><dl class="scammers"><dt>Мошенники:</dt><dd>0</dd></dl><dl class="errors"><dt>Ошибки:</dt><dd>0</dd>${await checkKeyValue("not-to-check-previously-checked") === "true" ? `<dl class="checked"><dt>Ранее проверялись:</dt><dd>0</dd></dl>` : ''}<dl class="remained"><dt>Осталось проверить:</dt><dd>${members.length}</dd></dl>`;
                visitorCountDl.appendChild(newFootnoteDiv)
            }

            let index = 0
            const checkNextMember = async () => {
                if (index >= members.length) {
                    return
                }

                const member = members[index]
                const usernameLink = member.querySelector('a.username')
                const usernameHref = usernameLink.getAttribute('href')
                const userStatCounters = member.querySelector('div.memberInfo')
                const gifId = `gif-${index}`

                userStatCounters.appendChild(createGifElement(gifId, 'https://i.imgur.com/I5VH0zp.gif', 24, 24))
                await checkUser(`https://${domain}/${usernameHref}shared-ips`, 'members', gifId)

                index++
                await checkNextMember()
            }

            checkNextMember().then()
        }
    }}

AutoCheckNewMembers()

function xenforoLogAndAlert(text, title) {
    console.log(text)
    XenForo.alert(`${text}`, `${title}`)
}

function encodeOutput(output) {
    const text = output.toString();
    return encodeURIComponent(text).replace("\n", "/%0A/g");
}

async function checkUser(link, source, gifId) {
    const notToCheckPreviouslyChecked = await checkKeyValue('not-to-check-previously-checked') === "true";
    const checkedList = (await checkKeyValue("checked-list")) || [];
    const checkedItem = checkedList.find(item => item.link === `${link.replace(/\/shared-ips/g, '').replace(/\/+$/, '')}/`.replace(new RegExp(`^(?!https://${domain})`), `https://${domain}/`));
    if (notToCheckPreviouslyChecked && checkedItem) {
        let date = checkedItem.date;
        let output = checkedItem.output + `\nРезультат проверки был сохранен ${date}`;
        let gifElement = document.getElementById(gifId);
        if (gifElement) {
            if (output.includes("мошенник")) {
                gifElement.src = 'https://i.imgur.com/g5GxNHD.png';
            } else if (output.includes("VPN")) {
                gifElement.src = 'https://i.imgur.com/o5qNA1o.png';
            } else {
                gifElement.src = 'https://i.imgur.com/i4OlWJk.png';
            }
            if (source === 'members' || source === 'registered') OnlineChangeTable('dl.checked', 1);
            gifElement.title = `${output}`;

            gifElement.addEventListener('click', async function onClick() {
                gifElement.removeEventListener('click', onClick);
                const index = checkedList.indexOf(checkedItem);
                if (index > -1) {
                    checkedList.splice(index, 1);
                    await changeItemValue("checked-list", checkedList);
                }
                gifElement.src = 'https://i.imgur.com/I5VH0zp.gif';
                checkUser(link, undefined, gifId);
            });
        } else {
            xenforoLogAndAlert(`${output}`, `Lolzteam Multiaccount Finder`);
        }
        return;
    }


    console.log(gifId)
    console.log(`${link.replace(/(https:\/\/.*?)\/\//g, '$1/').replace(/\/shared-ips/gi, "/shared-ips").replace(/(\/shared-ips)+/gi, "/shared-ips")}`)

    const response = await fetch(`${link.replace(/(https:\/\/.*?)\/\//g, '$1/').replace(/\/shared-ips/gi, "/shared-ips").replace(/(\/shared-ips)+/gi, "/shared-ips")}`)
    const data = await response.text()
    const parser = new DOMParser();
    const htmlDocument = parser.parseFromString(data, "text/html");
    const userLogs = htmlDocument.getElementsByClassName("userLog");
    let bannedUsersCount = 0;
    let nonBannedUsersCount = 0;
    let bannedThisMonthCount = 0;
    const numUserLogs = userLogs.length;
    const nameEl = htmlDocument.querySelector(`a.crumb[href^="https://${domain}/"] span`);
    const name = nameEl ? nameEl.textContent.trim() : "";
    console.log(name)
    const gifElement = document.getElementById(gifId);
    if (!name) {
        if (gifElement) {
            gifElement.src = 'https://i.imgur.com/wqXWudH.png'; // подгружаем иконку ошибки с imgur
        }
        OnlineChangeTable('dl.errors', 1);

        if (await checkKeyValue('retry-after-error') === "true") {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log("Retrying check for user:", link);
                    resolve(checkUser(link, source, gifId));
                }, 15000);
            });
        } else {
            throw new Error("Name not found");
        }
    }

    for (let i = 0; i < userLogs.length; i++) {
        const spans = userLogs[i].getElementsByTagName("span");
        let isBanned = false;
        for (let j = 0; j < spans.length; j++) {
            if (spans[j].classList.contains("banned")) {
                bannedUsersCount++;
                isBanned = true;
                const li = userLogs[i].querySelector('li.ipLog');
                if (li) {
                    const abbr = li.querySelector('abbr.DateTime');
                    const span = li.querySelector('span.DateTime');
                    if (abbr || span) {
                        const title = abbr ? abbr.getAttribute("data-datestring") : span.getAttribute("title");
                        if (title.includes(month) || title.includes('Сегодня') || title.includes('Вчера')) {
                            //console.log(title);
                            bannedThisMonthCount++;
                        }
                    }
                }
                break;
            }
        }
        if (!isBanned) {
            nonBannedUsersCount++;
        }
    }

    const totalUsers = bannedUsersCount + nonBannedUsersCount;
    const bannedPercent = totalUsers ? ((bannedUsersCount / totalUsers) * 100).toFixed(2) : 0;
    const nonBannedPercent = totalUsers ? ((nonBannedUsersCount / totalUsers) * 100).toFixed(2) : 0;
    const bannedThisMonthPercent = bannedUsersCount ? ((bannedThisMonthCount / bannedUsersCount) * 100).toFixed(2) : 0; // вычисляем процент заблокированных в текущем месяце

    const [showBlockedPercentage, showUnblockedPercentage, showTotalUsersIp, showBlockedThisMonthPercentage] = await Promise.all(["show-blocked-percentage", "show-unblocked-percentage", "show-total-users-ip", "show-blocked-this-month-percentage"].map(key => checkKeyValue(key).then(value => value === "true")));
    let output = `${showBlockedPercentage ? `\n% заблокированных: ${bannedPercent} (${bannedUsersCount})` : ''}${showUnblockedPercentage ? `\n% не заблокированных: ${nonBannedPercent} (${nonBannedUsersCount})` : ''}${showTotalUsersIp ? `\nОбщее количество пользователей в общих IP: ${numUserLogs}` : ''}${showBlockedThisMonthPercentage ? `\n% от заблокированных в этом месяце: ${bannedThisMonthPercent} (${bannedThisMonthCount})` : ''}`;

    function template(description) {
        let title = encodeOutput(`Жалоба на пользователя ${name}`)
        let message = encodeOutput(`[CLUB]1. Никнейм нарушителя и ссылка на профиль: ${link.replace('/shared-ips', '').replace(/\/+$/, '/')}\n2. Краткое описание жалобы: ${description}\n3. Доказательства: ${link.replace('/shared-ips', '').replace(/\/+$/, '/')}shared-ips/[/CLUB]`)
        const template = `https://${domain}/forums/801/create-thread?prefix_id=92&title=${title}&message=${message}`;
        window.open(`${template}`, '_blank');
    }

    if (htmlDocument.body.textContent.includes("Пользователей по заданным параметрам не найдено.") || htmlDocument.body.textContent.includes("No matching users were found.")) {
        gifElement && (gifElement.src = 'https://i.imgur.com/i4OlWJk.png');
        output = `${name} - пользователей по заданным параметрам не найдено.`;
        gifElement && (gifElement.title = `${output}`);
        !gifElement && xenforoLogAndAlert(`${output}`, `Lolzteam Multiaccount Finder`);
        if (source === 'members' || source === 'registered') OnlineChangeTable('dl.clean', 1);
    } else if (bannedUsersCount >= nonBannedUsersCount && bannedUsersCount !== 0) {
        output = output ? `${name} - мошенник ${output}` : `${name} - мошенник`;
        if (gifElement) {
            gifElement.src = 'https://i.imgur.com/g5GxNHD.png';
            gifElement.style.cursor = 'pointer';
            gifElement.title = `${output}`;
            if (source === 'members' || source === 'registered') OnlineChangeTable('dl.scammers', 1);
        } else {
            xenforoLogAndAlert(`${output}`, `Lolzteam Multiaccount Finder`);
        }
    } else if (nonBannedUsersCount > 15 && bannedUsersCount < nonBannedUsersCount / 3) {
        gifElement && (gifElement.src = 'https://i.imgur.com/o5qNA1o.png');
        output = output ? `${name} - использует VPN ${output}` : `${name} - использует VPN`;
        gifElement && (gifElement.title = `${output}`);
        !gifElement && xenforoLogAndAlert(`${output}`, `Lolzteam Multiaccount Finder`);
        if (source === 'members' || source === 'registered') OnlineChangeTable('dl.vpn', 1);
    } else if (nonBannedUsersCount > 6 && nonBannedUsersCount <= 15 && bannedUsersCount < nonBannedUsersCount / 2) {
        gifElement && (gifElement.src = 'https://i.imgur.com/o5qNA1o.png');
        output = output ? `${name} - возможно использует VPN ${output}` : `${name} - возможно использует VPN`;
        gifElement && (gifElement.title = `${output}`);
        !gifElement && xenforoLogAndAlert(`${output}`, `Lolzteam Multiaccount Finder`);
        if (source === 'members' || source === 'registered') OnlineChangeTable('dl.vpn', 1);
    } else if (bannedUsersCount > nonBannedUsersCount / 2) {
        output = output ? `${name} - возможно мошенник ${output}` : `${name} - возможно мошенник`;
        if (gifElement) {
            gifElement.src = 'https://i.imgur.com/g5GxNHD.png';
            gifElement.style.cursor = 'pointer';
            gifElement.title = `${output}`;
            if (source === 'members' || source === 'registered') OnlineChangeTable('dl.scammers', 1);
        } else {
            xenforoLogAndAlert(`${output}`, `Lolzteam Multiaccount Finder`);
        }
    } else {
        gifElement && (gifElement.src = 'https://i.imgur.com/i4OlWJk.png');
        output = output ? `${name} - мультиаккаунт ${output}` : `${name} - мультиаккаунт`;
        gifElement && (gifElement.title = `${output}`);
        !gifElement && xenforoLogAndAlert(`${output}`, `Lolzteam Multiaccount Finder`);
        if (source === 'members' || source === 'registered') OnlineChangeTable('dl.clean', 1);
    }
    if (notToCheckPreviouslyChecked) {
        link = link.replace(/\/shared-ips/g, ''); if (!link.endsWith('/')) { link += '/'; }
        if (!link.startsWith(`https://${domain}`)) {
            link = `https://${domain}/${link}`;
        }
        checkedList.push({ link: link.replace(/\/+$/, '/'), output: output, date: date.toLocaleString() });
        console.log(checkedList)
        await changeItemValue("checked-list", checkedList);
    }
    if (gifElement && output.includes("мошенник")) {
        gifElement.addEventListener('click', function () { template(output); });
    }}