☰

Semprot.com Bomber

Hides Semprot replies that lack images or links, keeping the main OP post safe.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Вам потребуется установить расширение, например Tampermonkey или Violentmonkey, чтобы установить этот скрипт.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Semprot.com Bomber
// @namespace    Violentmonkey Scripts
// @version      1.1.0
// @description  Hides Semprot replies that lack images or links, keeping the main OP post safe.
// @license      MIT
// @match        https://www.semprot.com/threads/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(async function() {
    'use strict';

    const cleanPath = window.location.pathname.replace(/\/page-\d+.*$/, '');
    const storageKey = 'xf_true_op_' + cleanPath;

    function getPostAuthor(post) {
        if (!post) return null;
        const dataAuthor = post.getAttribute('data-author');
        if (dataAuthor) return dataAuthor.trim();

        // Search for username elements, but explicitly ignore any inside quote blocks
        const usernames = post.querySelectorAll('.username, .message-name');
        for (let el of usernames) {
            if (!el.closest('.bbCodeBlock--quote')) {
                return el.textContent.trim();
            }
        }
        return null;
    }

    async function getOrFetchOpAuthor() {
        let opAuthor = sessionStorage.getItem(storageKey);
        if (opAuthor) return opAuthor;

        const posts = document.querySelectorAll('article.message--post');
        if (posts.length > 0 && !window.location.pathname.includes('/page-')) {
            opAuthor = getPostAuthor(posts[0]);
            if (opAuthor) {
                sessionStorage.setItem(storageKey, opAuthor);
                return opAuthor;
            }
        }

        try {
            const res = await fetch(cleanPath);
            const html = await res.text();
            const doc = new DOMParser().parseFromString(html, 'text/html');
            const firstPost = doc.querySelector('article.message--post');
            if (firstPost) {
                opAuthor = getPostAuthor(firstPost);
                if (opAuthor) {
                    sessionStorage.setItem(storageKey, opAuthor);
                    return opAuthor;
                }
            }
        } catch (err) {
            console.error('Could not fetch root OP:', err);
        }

        if (posts.length > 0) {
            opAuthor = getPostAuthor(posts[0]);
            if (opAuthor) sessionStorage.setItem(storageKey, opAuthor);
        }
        return opAuthor;
    }

    function hasMediaOrLink(post) {
        const messageBody = post.querySelector('.message-body, .bbWrapper');
        if (!messageBody) return false;

        // Check for real images/media, ignoring smilies
        const realImages = messageBody.querySelectorAll('img:not(.smilie), .bbImage, video, iframe, .bbMedia, picture');
        if (realImages.length > 0) return true;

        // Check for links, ignoring quotes and user mentions
        const links = messageBody.querySelectorAll('a');
        for (let a of links) {
            if (a.closest('.bbCodeBlock--quote')) continue;
            if (a.classList.contains('username') || a.hasAttribute('data-user-id')) continue;

            const href = a.getAttribute('href');
            if (href && !href.startsWith('#') && !href.startsWith('javascript:')) {
                return true;
            }
        }

        return false;
    }

    async function filterPosts() {
        const opAuthor = await getOrFetchOpAuthor();
        if (!opAuthor) return;

        const posts = document.querySelectorAll('article.message--post');
        const isPageOne = !window.location.pathname.includes('/page-') || window.location.pathname.endsWith('/page-1');

        posts.forEach((post, index) => {
            if (post.dataset.opProcessed) return;
            post.dataset.opProcessed = 'true';

            const postAuthor = getPostAuthor(post);

            // Nuke anyone who isn't the true OP
            if (postAuthor !== opAuthor) {
                post.style.display = 'none';
                return;
            }

            // Always keep page 1 opening post safe
            if (isPageOne && index === 0) {
                return;
            }

            // Nuke OP text-only replies that lack media or links
            if (!hasMediaOrLink(post)) {
                post.style.display = 'none';
            }
        });
    }

    await filterPosts();

    const observer = new MutationObserver(() => {
        filterPosts();
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();