Make Twitter Great Again

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Make Twitter Great Again
// @namespace    https://github.com/androidcn/userscripts/
// @version      2024-12-25
// @description  为Twitter增加两个按钮,快速让Twitter算法知道你“不感兴趣的推文“ From Chrome Extension "Make Twitter Great Again" not interesting this post
// @author       theopenprojects.io
// @match        https://twitter.com/home
// @match        https://x.com/home
// @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();
    });
})();