Block who retweeted this

Add a button to block everyone who retweeted a tweet.

// ==UserScript==
// @name         Block who retweeted this
// @namespace    http://tampermonkey.net/
// @version      0.51
// @description  Add a button to block everyone who retweeted a tweet.
// @author       CL Based on a script by KingSupernova
// @match        https://twitter.com/*
// @match        https://x.com/*
// @grant        GM_openInTab
// @grant        GM_addStyle
// @run-at       document-idle
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // Helper function to style the buttons according to Twitter's design
    function applyButtonStyles(button) {
        button.style.marginLeft = '10px';
        button.style.backgroundColor = '#e0245e';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.padding = '5px 12px';
        button.style.cursor = 'pointer';
        button.style.borderRadius = '9999px'; // Twitter's rounded button style
        button.style.fontSize = '13px';
        button.style.fontWeight = 'bold';
        button.style.textTransform = 'uppercase';
        button.style.fontFamily = 'TwitterChirp, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
        button.style.letterSpacing = '0.5px';
        button.style.transition = 'background-color 0.2s ease-in-out';
    }

    // Hover effect
    function applyButtonHoverEffect(button) {
        button.addEventListener('mouseover', function() {
            button.style.backgroundColor = '#c21d4b'; // Darker red on hover
        });
        button.addEventListener('mouseout', function() {
            button.style.backgroundColor = '#e0245e'; // Back to original color
        });
    }

    // Helper function to add the "Block who retweeted this" button under each tweet
    function addButtonToTweet() {
        let tweetButtons = document.querySelectorAll('[role="group"]');

        tweetButtons.forEach(buttonGroup => {
            // Check if the button already exists to prevent duplicates
            if (!buttonGroup.querySelector('.block-retweeters-button')) {
                let blockButton = document.createElement('button');
                blockButton.innerHTML = 'Block who retweeted this';
                blockButton.className = 'block-retweeters-button';

                // Apply styles and hover effect
                applyButtonStyles(blockButton);
                applyButtonHoverEffect(blockButton);

                blockButton.addEventListener('click', function() {
                    let tweetLink = buttonGroup.closest('article').querySelector('a[href*="/status/"]');
                    if (tweetLink) {
                        let tweetUrl = tweetLink.href;
                        let retweetUrl = tweetUrl + '/retweets';
                        // Open the retweets page in a new tab
                        GM_openInTab(retweetUrl, { active: true, insert: true, setParent: true });
                    }
                });
                buttonGroup.appendChild(blockButton);
            }
        });
    }

    // Helper function to add the block button on the retweets page
    function addButtonToRetweetsPage() {
        let retweetList = document.querySelector('[aria-label="Timeline: Reposts"]');
        if (retweetList && !document.querySelector('.block-retweets-button')) {
            let blockButton = document.createElement('button');
            blockButton.innerHTML = 'Block all retweeters';
            blockButton.className = 'block-retweets-button';
            blockButton.style.display = 'block';
            blockButton.style.margin = '10px auto';
            blockButton.style.padding = '10px 15px';
            blockButton.style.fontSize = '14px';
            blockButton.style.textAlign = 'center';

            // Apply styles and hover effect
            applyButtonStyles(blockButton);
            applyButtonHoverEffect(blockButton);

            blockButton.addEventListener('click', function() {
                runBlockScript();  // Run the block script when clicked
            });

            retweetList.parentNode.insertBefore(blockButton, retweetList);
        }
    }

    // Blocking script to block retweeters
    function runBlockScript() {
        const affectedAccountUrls = {};

        const getNextPerson = function() {
            let elements = Array.from(document.querySelectorAll('[aria-label="Timeline: Reposts"] > div > div'));
            for (let el of elements) {
                try {
                    let profileLink = el.firstChild.firstChild.firstChild.firstChild.children[1].firstChild.firstChild.firstChild.firstChild.firstChild;
                    if (profileLink.href && !affectedAccountUrls[profileLink.href]) return profileLink;
                } catch (err) {}
            }
            return false;
        };

        const findButton = function(username) {
            let dialog = document.querySelector('[data-testid="Dropdown"]') || document.querySelector('[data-testid="sheetDialog"]');
            let buttons = Array.from(dialog.children);
            for (let button of buttons) {
                if (button.children[1].firstChild.firstChild.textContent.startsWith(username + " @")) return button;
            }
            console.log("Could not find " + username.toLowerCase() + " button");
            return false;
        };

        const performActionOnPerson = async function(person, action) {
            for (affectedAccountUrls[person.href] = !0, person.click(); null === document.querySelector('[data-testid="userActions"]');)
                await sleep(10);
            for (document.querySelector('[data-testid="userActions"]').firstChild.click(); !document.querySelector('[data-testid="Dropdown"]') || document.querySelector('[data-testid="sheetDialog"]');)
                await sleep(10);
            let button = findButton(action);
            for (button && (button.click(), "Block" === action && (await sleep(50), document.querySelector('[data-testid="confirmationSheetConfirm"]').click()), await sleep(50)), history.back();
                null === document.querySelector('[aria-label="Timeline: Reposts"]');
            ) await sleep(10);
            return Boolean(button);
        };

        const scrollToNewPeople = async function() {
            let viewport = document.querySelector("[data-viewportview=true]") || document.documentElement;
            let lastScrollTop = viewport.scrollTop;
            let lastCheckTime = performance.now();
            for (; !getNextPerson();) {
                if (viewport.scrollTop += 100, lastScrollTop === viewport.scrollTop) {
                    if (performance.now()-lastCheckTime >= 2000) return;
                } else lastCheckTime = performance.now();
                lastScrollTop = viewport.scrollTop, await sleep(1);
            }
        };

        const performActionOnPeople = async function(action) {
            let count = 0;
            for (;;) {
                await scrollToNewPeople();
                let person = getNextPerson();
                if (person) {
                    let success = await performActionOnPerson(person, action);
                    success && count++;
                } else {
                    alert(count + " people " + action.toLowerCase() + "ed.");
                    return;
                }
            }
        };

        const sleep = async function(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        };

        // Start blocking retweeters
        performActionOnPeople('Block');
    }

    // Mutation observer to add buttons to new tweets and the retweets page
    const observer = new MutationObserver(() => {
        addButtonToTweet();
        addButtonToRetweetsPage();
    });

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

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址