Make Twitter Great Again

为Twitter增加两个按钮,快速让Twitter算法知道你“不感兴趣的推文“ From Chrome Extension "Make Twitter Great Again" not interesting this post

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

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

Tendrás que 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.

Tendrás que instalar una extensión como Tampermonkey antes de poder 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)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

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

// ==UserScript==
// @name         Make Twitter Great Again
// @namespace    https://github.com/androidcn/userscripts/
// @version      2026-05-13
// @description  为Twitter增加两个按钮,快速让Twitter算法知道你“不感兴趣的推文“ From Chrome Extension "Make Twitter Great Again" not interesting this post
// @author       theopenprojects.io
// @match        https://twitter.com/*
// @match        https://x.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=twitter.com
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// ==/UserScript==

var hideButton = document.createElement('button');
 function createButton() {
        // Create a button element
        hideButton.textContent = '隐藏';
        hideButton.style.position = 'fixed';
        hideButton.style.top = '60px';
        hideButton.style.right = '20px';
        hideButton.style.zIndex = '9999';
        // Append the button to the body
        document.body.appendChild(hideButton);
        // Add click event listener to the button
        hideButton.addEventListener('click', performHidedAction);
    }
function hideIt(){
    document.querySelector("header[role='banner']").style="display:none;";
    document.querySelector('div[aria-label="Home timeline"] div:first-child').style="display:none;";
    //console.log('已隐藏');
    hideButton.textContent = '显示';
    //GM_setValue("leftSideBar_hide",true);
}
function showIt(){
    document.querySelector("header[role='banner']").style="";
    document.querySelector('div[aria-label="Home timeline"] div:first-child').style="";
    //console.log('已显示');
    hideButton.textContent = '隐藏';
    //GM_setValue("leftSideBar_hide",false);
}
    function performHidedAction() {
        var HideText = hideButton.textContent ;
        if (HideText == "隐藏"){
            hideIt();
        }
        else{
             showIt();
        }
    }

    // Wait for the page to load
    window.addEventListener('load', createButton);
    //Scroll to hide lefe bar and top bar
    //window.addEventListener('scroll',hideIt);

const silencePath = 'path[d="M18 6.59V1.2L8.71 7H5.5C4.12 7 3 8.12 3 9.5v5C3 15.88 4.12 17 5.5 17h2.09l-2.3 2.29 1.42 1.42 15.5-15.5-1.42-1.42L18 6.59zm-8 8V8.55l6-3.75v3.79l-6 6zM5 9.5c0-.28.22-.5.5-.5H8v6H5.5c-.28 0-.5-.22-.5-.5v-5zm6.5 9.24l1.45-1.45L16 19.2V14l2 .02v8.78l-6.5-4.06z"]'
const shitPath = 'path[d="M9.5 7c.828 0 1.5 1.119 1.5 2.5S10.328 12 9.5 12 8 10.881 8 9.5 8.672 7 9.5 7zm5 0c.828 0 1.5 1.119 1.5 2.5s-.672 2.5-1.5 2.5S13 10.881 13 9.5 13.672 7 14.5 7zM12 22.25C6.348 22.25 1.75 17.652 1.75 12S6.348 1.75 12 1.75 22.25 6.348 22.25 12 17.652 22.25 12 22.25zm0-18.5c-4.549 0-8.25 3.701-8.25 8.25s3.701 8.25 8.25 8.25 8.25-3.701 8.25-8.25S16.549 3.75 12 3.75zM8.947 17.322l-1.896-.638C7.101 16.534 8.322 13 12 13s4.898 3.533 4.949 3.684l-1.897.633c-.031-.09-.828-2.316-3.051-2.316s-3.021 2.227-3.053 2.322z"]'
const moreProfilePath = 'path[d="M3 12c0-1.1.9-2 2-2s2 .9 2 2-.9 2-2 2-2-.9-2-2zm9 2c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm7 0c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"]'

const sleep = ms => new Promise(r => setTimeout(r, ms));

const waitForElm = (selector) => {
    return new Promise((resolve, reject) => {
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                const elm = mutation.target.querySelector(selector);
                if (elm) {
                    observer.disconnect();
                    resolve(elm);
                }
            });
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true,
        });
    });
};

const setTabStatusToBody = () => {
    const body = document.querySelector('body')
    if (!body || !document.querySelectorAll('[role="tablist"] [role="tab"]')) return
    //if (document.URL !== 'https://twitter.com/home') return;

    if (!Array.from(document.querySelectorAll('[role="tablist"] [role="tab"][data-index]')).length > 0) Array.from(document.querySelectorAll('[role="tablist"] [role="tab"]')).map((el, idx) => el.closest('div').setAttribute('data-index', idx + 1))

    const selectedIndexElm = document.querySelector('[role="tablist"] [role="tab"][aria-selected="true"]')
    if (selectedIndexElm) {
        const parent = selectedIndexElm.closest('div')
        if (parent) {
            body.setAttribute('data-make-twitter-great-again', parent.getAttribute('data-index'))
        }
    }
}

const createShityBtn = (tweet) => {
    if (!tweet || tweet.querySelector('.shitBtn')) return;
    //if (document.URL !== 'https://twitter.com/home') return;

    const button = document.createElement('button');
    tweet.setAttribute('data-shit', true);
    button.classList.add('shitBtn');
    button.innerHTML = '没兴趣';

    const navAction = tweet.querySelector('div[role="group"][id*="id__"]');
    if (navAction) navAction.appendChild(button);
}

const createSilenceBtn = tweet => {
    if (!tweet || tweet.querySelector('.silenceBtn')) return;
   // if (document.URL !== 'https://twitter.com/home') return;

    const button = document.createElement('button');
    tweet.setAttribute('data-silence', true);
    button.classList.add('silenceBtn');
    button.innerHTML = '封禁';

    const navAction = tweet.querySelector('div[role="group"][id*="id__"]');
    if (navAction) navAction.appendChild(button);
}

const handleBtnClick = async (e, selector) => {
    const tweet = e.target.closest('article');
    document.querySelector('body').setAttribute('data-pop-open', true)

    const btnDropdown = tweet.querySelector('[aria-haspopup="menu"][role="button"][data-testid="caret"]');
    if (!btnDropdown) return

    btnDropdown.click();

    await sleep(5);
    const dropdown = document.querySelector('[data-testid="Dropdown"],[data-testid="sheetDialog"]');
    if (!dropdown) return;
    
    const item = dropdown.querySelector(selector)
    if (item) item.closest('[role]').click()

    btnDropdown.click();

    if (document.querySelector('body').getAttribute('data-make-twitter-great-again') !== "1" || document.querySelector('body').getAttribute('data-make-twitter-great-again') !== "2") tweet.remove()
}

const handleProfileBtnClick = async (e, selector) => {
    const userActions = document.querySelector('[role="main"] [data-testid="userActions"]')
    if (!userActions) return

    document.querySelector('body').setAttribute('data-pop-open', true)

    const path = userActions.querySelector(moreProfilePath);
    if (!path) return
    const btnDropdown = path.closest('div[dir]')
    if (!btnDropdown) return

    btnDropdown.click();

    await sleep(5);
    const dropdown = document.querySelector('[data-testid="Dropdown"]');
    if (!dropdown) return;

    const item = dropdown.querySelector(selector)
    if (item) item.closest('[role]').click()

    dropdown.remove()
}

const addBtnToTweets = () => {
    const tweets = document.querySelectorAll('[role="region"] article:not([data-shit]):not([data-silence])');
    if (tweets && tweets.length > 0) tweets.forEach(tweet => {
        createShityBtn(tweet)
        createSilenceBtn(tweet)
    });
}

const addProfileSilenceBtn = () => {
    const userActions = document.querySelector('[role="main"] [data-testid="userActions"]')
    if (!userActions) return

    const contentActions = userActions.parentElement
    if (!contentActions || contentActions.getAttribute('data-silence') === 'true') return

    const button = document.createElement('button');
    contentActions.setAttribute('data-silence', true);
    button.classList.add('profileSilence');
    button.innerHTML = '🤫';

    contentActions.insertBefore(button, contentActions.firstChild);
}

const isProfile = () => {
    if (document.querySelector('head meta[content*="twitter://user?screen_name="]')) {
        document.querySelector('body').setAttribute('data-profile', true)

        addProfileSilenceBtn()
    }
    else document.querySelector('body').removeAttribute('data-profile')
}

const observeTweets = () => {
    const observer = new MutationObserver((mutations) => {
        setTabStatusToBody();
        isProfile()
        if (!document.querySelector('[data-make-twitter-great-again] [role="group"] > div > [role="menu"]')) document.querySelector('body').removeAttribute('data-pop-open')
        mutations.forEach(() => addBtnToTweets());
    });
    observer.observe(document.body, {
        childList: true,
        subtree: true,
    });
    return observer;
}

(async () => {
    await waitForElm('[role="region"] article');

    setTabStatusToBody();
    isProfile();
    addBtnToTweets();

    document.addEventListener('click', (e) => {
        if (e.target.classList.contains('shitBtn')) handleBtnClick(e, shitPath);
        if (e.target.classList.contains('silenceBtn')) handleBtnClick(e, silencePath);
        if (e.target.classList.contains('profileSilence')) handleProfileBtnClick(e, silencePath);
    })

    const tweetsObserver = observeTweets();
    window.addEventListener('beforeunload', () => {
        tweetsObserver.disconnect();
    });
})();