Greasy Fork

Greasy Fork is available in English.

X/Twitter 1 Click report spam and block

Report spam and block profiles with 1 click

当前为 2024-05-16 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        X/Twitter 1 Click report spam and block
// @description Report spam and block profiles with 1 click
// @version     1.0
// @grant       none
// @match       https://twitter.com/*
// @match       https://x.com/*
// @author      incognico
// @icon        https://www.google.com/s2/favicons?sz=64&domain=x.com
// @require     https://cdn.jsdelivr.net/npm/@violentmonkey/dom@2
// @license     GPL v3
// @author      incognico
// @namespace   http://greasyfork.icu/users/931787
//
// ==/UserScript==


const accountMenuIconSelector = '[data-testid="primaryColumn"] svg:has([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 ourIconId = '1clickreportbtn';
const reportIconSelector = '[data-testid="Dropdown"] svg:has([d="M3 2h18.61l-3.5 7 3.5 7H5v6H3V2zm2 12h13.38l-2.5-5 2.5-5H5v10z"])';
const spamItemSelector = '[data-viewportview="true"] [role="radiogroup"] label:nth-child(6)';
const nextButtonSelector = '[data-testid="ChoiceSelectionNextButton"]';
const modalButtonsSelector = '[data-viewportview="true"] button';

const wait = (ms) => {
    return new Promise(resolve => setTimeout(resolve, ms));
};

const doReport = async (event) => {
    if (!event.shiftKey) {
        alert('Press shift to confirm reporting this account as spam and blocking');
        return;
    }
    // open account overflow menu
    document.querySelector(accountMenuIconSelector).parentElement.click();
    await wait(100);
    // press report
    document.querySelector(reportIconSelector).parentElement.parentElement.click();
    await wait(850);
    // select spam and press next
    document.querySelector(spamItemSelector).click();
    document.querySelector(nextButtonSelector).click();
    await wait(500);
    // second button is report
    document.querySelectorAll(modalButtonsSelector)[1].click();
};


const destroyIcon = () => {
    const icon = document.getElementById(ourIconId);
    if (icon) {
        icon.remove();
    }
};


const createIconIfNotExists = (accountMenuIcon) => {
    const iconExists = document.getElementById(ourIconId);
    if (!iconExists) {
        const icon = document.createElement('button');
        icon.id = ourIconId;
        icon.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M8 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h5.697" /><path d="M18 14v4h4" /><path d="M18 11v-4a2 2 0 0 0 -2 -2h-2" /><path d="M8 3m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z" /><path d="M18 18m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0" /><path d="M8 11h4" /><path d="M8 15h3" /></svg>`;
        icon.title = '1-Click spam report & block';
        icon.onclick = doReport;

        // assign style to the button
        const style = {
            color: 'black',
            textAlign: 'center',
            fontWeight: 'bold',
            alignSelf: 'baseline',
            borderRadius: '50%',
            borderColor: 'rgba(0, 0, 0, 0)',
            marginRight: '5px',
            marginLeft: '5px',
            backgroundColor: 'rgb(239, 243, 244)',
            boxShadow: '0 0 10px 0 rgba(0, 255, 0, 0.5)',
            fontFamily: 'TwitterChirp, sans-serif',
            cursor: 'pointer',
        };
        Object.assign(icon.style, style);

        // append icon to the profile icon list
        const header = accountMenuIcon.parentElement?.parentElement?.parentElement;
        if (header) {
            header.appendChild(icon);
        }
    }
};

const disconnect = VM.observe(document.body, () => {
    // append our icon on profile pages
    const profilePage = document.querySelector('[data-testid="UserName"]');
    if (profilePage) {
        const accountMenuIcon = document.querySelector(accountMenuIconSelector);
        createIconIfNotExists(accountMenuIcon);
    } else {
        destroyIcon();
    }
});