Загрузка...

[Tm] lolzhide - hiding blocked users on the forum

Thread in Extentions created by ЧерноеСердце Apr 22, 2025. (bumped May 23, 2025) 659 views

  1. ЧерноеСердце
    LolzHide
    Полное скрытие заблокированных пользователей на форуме

    Описание

    LolzHide — это мощное расширение для Tampermonkey, которое полностью удаляет весь контент от пользователей, находящихся в вашем черном списке. В отличие от стандартной функции игнорирования, скрипт не просто скрывает сообщения, а физически удаляет их из DOM-структуры страницы.

    Что умеет скрипт:
    • Полностью удаляет сообщения заблокированных пользователей в темах
    • Удаляет все комментарии от заблокированных пользователей
    • Скрывает темы, созданные заблокированными пользователями, из списков
    • Ведёт подробную статистику удаленного контента в консоли браузера
    • Работает с динамически подгружаемым контентом

    Преимущества:
    • Контент полностью исчезает со страницы (не остается пустых блоков)
    • Страницы становятся чище и компактнее
    • Мгновенно работает с новыми заблокированными пользователями
    • Не влияет на производительность форума
    • Не вмешивается в работу форума и не затрагивает рекламу

    Инструкция по установке

    1. Установите расширение Tampermonkeyдля вашего браузера:
    2. Нажмите на значок Tampermonkey в правом верхнем углу браузера и выберите "Создать новый скрипт"
    3. Удалите стандартный код и вставьте код скрипта из блока ниже
    4. Сохраните скрипт, нажав Ctrl+S
    5. Перезагрузите страницу форума

    Демонстрация работы

    После установки и запуска скрипта вы увидите в консоли браузера (F12 → вкладка Console) следующую информацию:

    Code
    [ЧС-Скрипт] Скрипт запущен
    [ЧС-Скрипт] Найдено 20 заблокированных пользователей
    [ЧС-Скрипт] Заблокированные пользователи: 005, Knesset, SalviaQeenzi, gonome, Хомиак, Alex, ArchiveKorol, СкладЧебупиццы, Блядес, AnimeHeHe, MALWARE, кошак, StrangeR, бережнюк, FLUGALAYZ, kusyaka, КрИпКрИпОчЕк, лолзтим, Shiva, пиздатый
    [ЧС-Скрипт] Удалено элементов: 5. Всего: 5
    [ЧС-Скрипт] Удалено по типам: сообщение: 2, комментарий: 2, тема в списке: 1
    [ЧС-Скрипт] Удалено по пользователям: кошак: 3, СкладЧебупиццы: 1, пиздатый: 1
    До и После

    • До: Сообщения от заблокированных пользователей отображаются как свернутые блоки
    • После: Сообщения полностью удаляются из страницы — их как будто никогда не было!

    Код скрипта

    Code

    // ==UserScript==
    // @name Lolzteam - Скрыть заблокированных пользователей
    // @namespace [URL]https://lolz.live/[/URL]
    // @version 1.1
    // @description Полностью скрывает сообщения, комментарии, темы, сообщения в чате и reply от/на заблокированных пользователей
    // @author ЧерноеСердце
    // @match [URL]https://lolz.live/*[/URL]
    // @match [URL]https://zelenka.guru/*[/URL]
    // @grant unsafeWindow
    // @run-at document-start
    // ==/UserScript==

    (function() {
    'use strict';

    // Настройки
    const config = {
    enableLogs: true, // **** в консоли
    actuallyRemove: true, // true - удалять, false - скрывать
    logPrefix: '[ЧС-Скрипт]', // Префикс для *****
    detailedReport: true // Подробная статистика
    };

    // Кэш
    const cache = {
    ignoredUsers: null,
    lastLogTimes: {},
    removedElements: 0,
    totalRemovedElements: 0,
    processingMutation: false,
    removedDetails: []
    };

    // Логирование
    function log(message, type = 'info') {
    if (!config.enableLogs) return;

    switch(type) {
    case 'info': console.info(`${config.logPrefix} ${message}`); break;
    case 'warn': console.warn(`${config.logPrefix} ${message}`); break;
    case 'error': console.error(`${config.logPrefix} ${message}`); break;
    default: console.log(`${config.logPrefix} ${message}`);
    }
    }

    // Получение списка ЧС
    function getIgnoredUsers() {
    console.log(`[ЧС-Скрипт] getIgnoredUsers вызван, кэш: ${cache.ignoredUsers}`);

    if (cache.ignoredUsers !== null) {
    console.log(`[ЧС-Скрипт] Возвращаем из кэша: ${cache.ignoredUsers.length} пользователей`);
    return cache.ignoredUsers;
    }

    try {
    // Пробуем через обычный доступ и через unsafeWindow
    const xf = typeof XenForo !== 'undefined' ? XenForo : (unsafeWindow && unsafeWindow.XenForo ? unsafeWindow.XenForo : null);

    console.log(`[ЧС-Скрипт] Проверка XenForo: обычный=${typeof XenForo !== 'undefined' ? 'найден' : 'не найден'}, unsafeWindow=${unsafeWindow && unsafeWindow.XenForo ? 'найден' : 'не найден'}`);

    if (xf) {
    console.log(`[ЧС-Скрипт] XenForo._ignoredUsers: ${xf._ignoredUsers ? 'найден' : 'не найден'}`);

    if (xf._ignoredUsers) {
    console.log(`[ЧС-Скрипт] Содержимое _ignoredUsers:`, xf._ignoredUsers);

    const users = Object.keys(xf._ignoredUsers);
    console.log(`[ЧС-Скрипт] Количество ключей: ${users.length}`);

    if (users.length > 0) {
    log(`Найдено ${users.length} заблокированных пользователей`);

    if (config.detailedReport) {
    const usernames = users.map(userId => {
    return xf._ignoredUsers[userId].username;
    }).join(', ');
    log(`Заблокированные пользователи: ${usernames}`);
    }

    cache.ignoredUsers = users;
    return users;
    } else {
    console.log(`[ЧС-Скрипт] _ignoredUsers пуст`);
    }
    } else {
    console.log(`[ЧС-Скрипт] XenForo._ignoredUsers отсутствует`);
    }
    } else {
    console.log(`[ЧС-Скрипт] XenForo не определен через оба способа`);
    }
    } catch(e) {
    log(`Ошибка получения ЧС: ${e.message}`, 'error');
    }

    cache.ignoredUsers = [];
    return [];
    }

    // Удаление элемента
    function removeElement(element, reason, username = '') {
    if (!element) return false;


    if (config.detailedReport) {
    cache.removedDetails.push({
    type: reason,
    username: username || 'неизвестно'
    });
    }

    if (config.actuallyRemove) {
    element.remove();
    console.log(`[ЧС-Скрипт] Элемент удален для ${username}`);
    } else {
    element.style.display = 'none';
    console.log(`[ЧС-Скрипт] Элемент скрыт для ${username}`);
    }

    cache.removedElements++;
    cache.totalRemovedElements++;
    return true;
    }

    // Вывод отчета
    function showDetailedReport() {
    if (!config.detailedReport || cache.removedDetails.length === 0) return;

    const typeCount = {};
    const userCount = {};

    cache.removedDetails.forEach(detail => {
    typeCount[detail.type] = (typeCount[detail.type] || 0) + 1;
    userCount[detail.username] = (userCount[detail.username] || 0) + 1;
    });

    const typeReport = Object.entries(typeCount)
    .map(([type, count]) => `${type}: ${count}`)
    .join(', ');

    const userReport = Object.entries(userCount)
    .map(([username, count]) => `${username}: ${count}`)
    .sort((a, b) => b.split(': ')[1] - a.split(': ')[1])
    .join(', ');

    log(`Удалено по типам: ${typeReport}`);
    log(`Удалено по пользователям: ${userReport}`);

    cache.removedDetails = [];
    }

    // Основная функция удаления контента
    function removeBlockedContent() {
    console.log('[ЧС-Скрипт] СТАРТ removeBlockedContent');
    if (cache.processingMutation) {
    console.log('[ЧС-Скрипт] Уже обрабатывается, выход');
    return;
    }
    cache.processingMutation = true;

    cache.removedElements = 0;
    cache.removedDetails = [];

    // Принудительно сбрасываем кэш заблокированных пользователей
    cache.ignoredUsers = null;

    try {
    // Удаление комментариев и сообщений
    document.querySelectorAll('.messageText.ignored, .messageText.baseHtml.SelectQuoteContainer.ignored').forEach(function(element) {
    const commentParent = element.closest('.comment');
    const messageParent = element.closest('.message');

    let username = 'неизвестно';
    try {
    const usernameElement = (commentParent || messageParent).querySelector('.username');
    if (usernameElement) {
    username = usernameElement.textContent.trim();
    }
    } catch(e) {}

    if (commentParent) {
    removeElement(commentParent, 'комментарий', username);
    } else if (messageParent) {
    removeElement(messageParent, 'сообщение', username);
    }
    });

    // Удаление тем с классом ignored
    document.querySelectorAll('.discussionListItem.ignored').forEach(function(item) {
    let username = 'неизвестно';
    try {
    const usernameElement = item.querySelector('.username.threadCreator');
    if (usernameElement) {
    username = usernameElement.textContent.trim();
    }
    } catch(e) {}

    removeElement(item, 'тема в списке', username);
    });

    // Поиск и удаление тем от пользователей в ЧС
    const ignoredUsers = getIgnoredUsers();
    console.log(`[ЧС-Скрипт] Получен список ЧС: ${ignoredUsers.length} пользователей`);
    // Получаем ссылку на XenForo объект
    const xf = typeof XenForo !== 'undefined' ? XenForo : (unsafeWindow && unsafeWindow.XenForo ? unsafeWindow.XenForo : null);

    if (ignoredUsers.length > 0 && xf && xf._ignoredUsers) {
    document.querySelectorAll('.discussionListItem').forEach(function(item) {
    const usernameElement = item.querySelector('.username.threadCreator');
    if (usernameElement) {
    const dataHref = usernameElement.getAttribute('data-href') || '';
    const userText = usernameElement.textContent.toLowerCase().trim();

    for (let i = 0; i < ignoredUsers.length; i++) {
    try {
    const userId = ignoredUsers[i];
    if (!xf._ignoredUsers[userId]) continue;

    const username = xf._ignoredUsers[userId].username;
    const usernameLower = username.toLowerCase();

    if (dataHref.toLowerCase().includes(usernameLower) || userText.includes(usernameLower)) {
    removeElement(item, 'тема пользователя', username);
    break;
    }
    } catch(e) {}
    }
    }
    });

    // Удаление сообщений в чате от заблокированных пользователей
    const chatMessages = document.querySelectorAll('.chat2-message');
    console.log(`[ЧС-Скрипт] Найдено сообщений в чате: ${chatMessages.length}`);

    chatMessages.forEach(function(chatMessage) {
    const usernameElement = chatMessage.querySelector('.chat2-message-username a.username.poster');
    if (usernameElement) {
    const href = usernameElement.getAttribute('href') || '';

    // Ищем имя пользователя в span с стилями
    const usernameSpan = usernameElement.querySelector('span[style]');
    let userText = '';
    if (usernameSpan) {
    userText = usernameSpan.textContent.toLowerCase().trim();
    } else {
    userText = usernameElement.textContent.toLowerCase().trim();
    }


    for (let i = 0; i < ignoredUsers.length; i++) {
    try {
    const userId = ignoredUsers[i];
    if (!xf._ignoredUsers[userId]) continue;

    const username = xf._ignoredUsers[userId].username;
    const usernameLower = username.toLowerCase();


    if (href.includes(`members/${userId}/`) ||
    href.toLowerCase().includes(usernameLower) ||
    userText === usernameLower ||
    userText.includes(usernameLower)) {


    removeElement(chatMessage, 'сообщение в чате', username);
    break;
    }
    } catch(e) {}
    }
    }
    });

    // Скрытие сообщений с reply от/на заблокированных пользователей
    document.querySelectorAll('.chat2-message .reply-message').forEach(function(replyMessage) {
    const replyTextLabel = replyMessage.querySelector('.chat2-reply-text-label');
    if (replyTextLabel) {
    const usernameSpan = replyTextLabel.querySelector('span[style]');
    if (usernameSpan) {
    const replyUsername = usernameSpan.textContent.toLowerCase().trim();

    for (let i = 0; i < ignoredUsers.length; i++) {
    try {
    const userId = ignoredUsers[i];
    if (!xf._ignoredUsers[userId]) continue;

    const username = xf._ignoredUsers[userId].username;
    const usernameLower = username.toLowerCase();

    if (replyUsername === usernameLower || replyUsername.includes(usernameLower)) {
    const parentMessage = replyMessage.closest('.chat2-message');
    if (parentMessage) {
    removeElement(parentMessage, 'сообщение с/на ЧС', username);
    break;
    }
    }
    } catch(e) {}
    }
    }
    }
    });
    }

    if (cache.removedElements > 0) {
    log(`Удалено элементов: ${cache.removedElements}. Всего: ${cache.totalRemovedElements}`);

    if (config.detailedReport) {
    showDetailedReport();
    }
    }
    } catch(e) {
    log(`Ошибка: ${e.message}`, 'error');
    } finally {
    cache.processingMutation = false;
    console.log('[ЧС-Скрипт] КОНЕЦ removeBlockedContent');
    }
    }

    // Определение значимых мутаций
    function shouldProcessMutation(mutations) {
    for (const mutation of mutations) {
    if (mutation.addedNodes.length === 0) continue;

    for (let i = 0; i < mutation.addedNodes.length; i++) {
    const node = mutation.addedNodes[i];

    if (node.nodeType !== Node.ELEMENT_NODE) continue;

    if (node.classList &&
    (node.classList.contains('message') ||
    node.classList.contains('comment') ||
    node.classList.contains('discussionListItem') ||
    node.classList.contains('chat2-message') ||
    node.querySelector('.message, .comment, .discussionListItem, .chat2-message, .reply-message'))) {
    return true;
    }

    if (node.querySelectorAll) {
    const childCount = node.querySelectorAll('*').length;
    if (childCount > 5) {
    return true;
    }
    }
    }
    }

    return false;
    }

    // Защита от слишком частых вызовов
    let debounceTimer = null;

    function debouncedRemoveContent() {
    if (debounceTimer) {
    clearTimeout(debounceTimer);
    }
    debounceTimer = setTimeout(removeBlockedContent, 100);
    }

    // Функция с повторными попытками
    function tryRemoveContentWithRetry(attempt = 1, maxAttempts = 40) {
    console.log(`[ЧС-Скрипт] Попытка ${attempt} из ${maxAttempts}`);

    // Сбрасываем кэш для повторной проверки
    cache.ignoredUsers = null;
    const ignoredUsers = getIgnoredUsers();

    if (ignoredUsers.length > 0) {
    console.log(`[ЧС-Скрипт] ✓ XenForo загружен, найдено ${ignoredUsers.length} пользователей в ЧС`);
    debouncedRemoveContent();
    return;
    }

    if (attempt < maxAttempts) {
    setTimeout(() => {
    tryRemoveContentWithRetry(attempt + 1, maxAttempts);
    }, 250); // Проверяем каждые 250мс (чаще)
    } else {
    console.log('[ЧС-Скрипт] Максимальное количество попыток достигнуто. XenForo._ignoredUsers не найден');
    }
    }

    // Принудительный сброс кэша при каждом запуске removeBlockedContent
    function resetCacheAndCheckAgain() {
    console.log('[ЧС-Скрипт] Принудительный сброс кэша');
    cache.ignoredUsers = null;
    const ignoredUsers = getIgnoredUsers();

    if (ignoredUsers.length > 0) {
    console.log(`[ЧС-Скрипт] ✓ После сброса кэша найдено ${ignoredUsers.length} пользователей`);
    }
    }

    // Старт при загрузке
    document.addEventListener('DOMContentLoaded', function() {
    log('Скрипт запущен');
    tryRemoveContentWithRetry();

    // MutationObserver для отслеживания изменений
    const observer = new MutationObserver(function(mutations) {
    // Проверяем загрузился ли XenForo
    const xf = typeof XenForo !== 'undefined' ? XenForo : (unsafeWindow && unsafeWindow.XenForo ? unsafeWindow.XenForo : null);
    if (xf && xf._ignoredUsers) {
    const currentUsers = Object.keys(xf._ignoredUsers);

    // Если у нас кэш пуст, а XenForo содержит пользователей - запускаем
    if (currentUsers.length > 0 && (!cache.ignoredUsers || cache.ignoredUsers.length === 0)) {
    console.log('[ЧС-Скрипт] XenForo обнаружен через MutationObserver!');
    console.log(`[ЧС-Скрипт] Найдено ${currentUsers.length} заблокированных пользователей`);
    cache.ignoredUsers = null; // Сбрасываем кэш
    debouncedRemoveContent();
    }
    }

    if (shouldProcessMutation(mutations)) {
    log('Обнаружены изменения');
    debouncedRemoveContent();
    }
    });

    observer.observe(document.body, {
    childList: true,
    subtree: true
    });

    // Дополнительная проверка каждые 1000мс на случай если MutationObserver пропустит
    const intervalCheck = setInterval(() => {
    const xf = typeof XenForo !== 'undefined' ? XenForo : (unsafeWindow && unsafeWindow.XenForo ? unsafeWindow.XenForo : null);
    if (xf && xf._ignoredUsers) {
    const currentUsers = Object.keys(xf._ignoredUsers);

    // Если у нас кэш пуст, а XenForo содержит пользователей - запускаем
    if (currentUsers.length > 0 && (!cache.ignoredUsers || cache.ignoredUsers.length === 0)) {
    console.log('[ЧС-Скрипт] XenForo обнаружен через интервал!');
    console.log(`[ЧС-Скрипт] Найдено ${currentUsers.length} заблокированных пользователей`);
    cache.ignoredUsers = null; // Сбрасываем кэш
    debouncedRemoveContent();
    clearInterval(intervalCheck); // Останавливаем проверку
    }
    }
    }, 1000);

    // Останавливаем проверку через 30 секунд в любом случае
    setTimeout(() => {
    clearInterval(intervalCheck);
    }, 30000);
    });

    // Ранний запуск
    if (document.readyState === 'interactive' || document.readyState === 'complete') {
    tryRemoveContentWithRetry();
    }

    // Функция для поиска заблокированных пользователей везде
    window.findIgnoredUsersAnywhere = function() {
    console.log('=== ПОИСК ЗАБЛОКИРОВАННЫХ ПОЛЬЗОВАТЕЛЕЙ ===');

    // Проверяем разные возможные места
    const checks = [
    { name: 'window.XenForo', obj: window.XenForo },
    { name: 'window._XenForo', obj: window._XenForo },
    { name: 'window.xenforo', obj: window.xenforo },
    { name: 'window.ignoredUsers', obj: window.ignoredUsers },
    { name: 'window._ignoredUsers', obj: window._ignoredUsers },
    { name: 'window.blockedUsers', obj: window.blockedUsers },
    { name: 'window._blockedUsers', obj: window._blockedUsers },
    { name: 'window.chat', obj: window.chat },
    { name: 'window.Chat', obj: window.Chat },
    { name: 'window.CHAT', obj: window.CHAT }
    ];

    checks.forEach(check => {
    if (check.obj) {
    console.log(`✓ ${check.name} найден:`, check.obj);

    // Ищем _ignoredUsers внутри объекта
    if (check.obj._ignoredUsers) {
    console.log(` └─ ${check.name}._ignoredUsers:`, check.obj._ignoredUsers);
    }
    if (check.obj.ignoredUsers) {
    console.log(` └─ ${check.name}.ignoredUsers:`, check.obj.ignoredUsers);
    }
    } else {
    console.log(`✗ ${check.name} не найден`);
    }
    });

    // Ищем во всех глобальных переменных
    console.log('\n=== ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ СОДЕРЖАЩИЕ "ignore" ===');
    Object.keys(window).forEach(key => {
    if (key.toLowerCase().includes('ignore') || key.toLowerCase().includes('block')) {
    console.log(`window.${key}:`, window[key]);
    }
    });

    return 'Поиск завершен';
    };

    // Функция для ручного тестирования из консоли
    window.testIgnoredUsers = function() {
    console.log('=== РУЧНОЙ ТЕСТ ===');
    cache.ignoredUsers = null; // Сбрасываем кэш
    const users = getIgnoredUsers();
    console.log(`Результат: ${users.length} пользователей`);
    return users;
    };
    })();

    Настройка скрипта

    Вы можете настроить скрипт под свои потребности, изменив параметры в начале кода:

    Code

    const config = {
    enableLogs: true, // Включить/выключить **** в консоли
    actuallyRemove: true, // true - полностью удалять, false - только скрывать
    logPrefix: '[ЧС-Скрипт]', // Префикс для *****
    detailedReport: true // Подробная статистика по удалениям
    };
    Параметры:
    • enableLogs: если установлено true, скрипт будет выводить информацию в консоль браузера
    • actuallyRemove: если установлено true, элементы будут полностью удаляться; если false — только скрываться через CSS
    • logPrefix: префикс для сообщений в консоли, поможет отличить сообщения скрипта
    • detailedReport: если установлено true, будет выводиться подробная статистика по удаленным элементам

    Дополнительная информация

    • Совместимость: Скрипт работает со всеми современными браузерами и не конфликтует с другими скриптами
    • Производительность: Скрипт оптимизирован и использует дебаунсинг для минимального влияния на производительность
    • Обновление ЧС: Скрипт автоматически подхватывает изменения в вашем черном списке, не требуя перезагрузки
    • Безопасность: Скрипт не отправляет никаких данных на сторонние серверы и работает полностью локально

    Вопрос: Работает ли скрипт с ночной темой?
    Ответ: Да, скрипт полностью совместим со всеми темами форума.

    Вопрос: Куда деваются сообщения после удаления?
    Ответ: Сообщения полностью удаляются из DOM-структуры страницы, как будто их никогда не было.

    Вопрос: Влияет ли скрипт на скорость загрузки страницы?
    Ответ: Влияние минимально благодаря оптимизации и использованию дебаунсинга.

    Вопрос: Нужно ли обновлять скрипт при добавлении новых пользователей в ЧС?
    Ответ: Нет, скрипт автоматически обрабатывает всех пользователей в вашем черном списке.
    Обратная связь

    Если у вас есть вопросы, предложения или вы нашли ошибку — оставляйте комментарии ниже. Буду рад помочь и улучшить скрипт!

    Скрипт регулярно обновляется. Следите за новыми версиями!
     
    This article was useful for you?
    You can thank the author of the topic by transferring funds to your balance
    Thank the author
  2. llimonix
    llimonix Apr 22, 2025
    Telegram: View @XomiachiyNovostnik
    29,128 Jan 20, 2020
    :amtap: наконец то я не буду видеть Показать игнорируемый контент
     
    1. a911
      avatarllimonix , зачем в чс людей кидаешь?
  3. awaw
    awaw Apr 27, 2025 ну купи парсер чатов тг lolz.live/threads/9046721 11,294 Oct 8, 2017
    мне не нужно, но за старание респект. выглядит реально круто
     
  4. gonome
    О, как раз то, о чем я просил! Если я заблокал пользователя - значит, я вообще не хочу его видеть.
     
  5. КинДзаДза
    КинДзаДза May 19, 2025 Banned 21,044 Jan 26, 2022
    Полезно, но не стоит забывать своих врагов.
     
  6. ЧерноеСердце
    обновка :)
    + добавил скрытие в общем чате

    :krutoy:
     
    1. ЧерноеСердце Topic starter
      avatarllimonix там с лолза забыл паренька убрать с кода, пасхалко, на нем проверка была в чате
    2. llimonix
Loading...