Greasy Fork

Greasy Fork is available in English.

Twitter畅享自由浏览推特

Twitter畅享自由浏览推特 - 您可以轻松解决推特访问问题。无论您身在何处,这款工具能够帮助您快速、稳定地访问推特,畅享全球动态,与世界分享您的想法和见解。不再受到地理限制,您将能够与全球用户交流互动,获取最新的新闻、趋势和内容。无需担心网络封锁和限制,立即体验畅快的推特浏览,与全球连接,发现更多精彩。

当前为 2023-06-21 提交的版本,查看 最新版本

在您安装前,Greasy Fork 希望您知道此脚本声明其包含了一些负面功能。这些功能也许会使脚本作者获利,而不能给您带来任何直接的金钱收益。

您只有在付费后才能使用脚本的全部功能。Greasy Fork 未参与到支付的流程,因此无法验证您是否获得了有价值的东西,亦无法帮助您申请退款。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Twitter畅享自由浏览推特
// @name:zh-CN   Twitter畅享自由浏览推特
// @name:zh-TW   Twitter暢享自由瀏覽推特
// @name:en      Twitter Enjoy the freedom to browse Twitter
// @namespace    Twitter-Pass-Tools
// @version      1.0.3
// @description  Twitter畅享自由浏览推特 - 您可以轻松解决推特访问问题。无论您身在何处,这款工具能够帮助您快速、稳定地访问推特,畅享全球动态,与世界分享您的想法和见解。不再受到地理限制,您将能够与全球用户交流互动,获取最新的新闻、趋势和内容。无需担心网络封锁和限制,立即体验畅快的推特浏览,与全球连接,发现更多精彩。
// @description:zh-CN  Twitter畅享自由浏览推特 - 您可以轻松解决推特访问问题。无论您身在何处,这款工具能够帮助您快速、稳定地访问推特,畅享全球动态,与世界分享您的想法和见解。不再受到地理限制,您将能够与全球用户交流互动,获取最新的新闻、趋势和内容。无需担心网络封锁和限制,立即体验畅快的推特浏览,与全球连接,发现更多精彩。
// @description:zh-TW  Twitter暢享自由瀏覽推特 - 您可以輕鬆解決推特訪問問題。無論您身在何處,這款工具能夠幫助您快速、穩定地訪問推特,暢享全球動態,與世界分享您的想法和見解。不再受到地理限制,您將能夠與全球用戶交流互動,獲取最新的新聞、趨勢和內容。無需擔心網絡封鎖和限制,立即體驗暢快的推特瀏覽,與全球連接,發現更多精彩。
// @description:en  Twitter Enjoy Free Browsing on Twitter - You can easily solve Twitter access problems. No matter where you are, this tool can help you quickly and stably access Twitter, enjoy global updates, and share your thoughts and insights with the world. No longer restricted by geography, you'll be able to connect with users around the world and get the latest news, trends and content.
// @author       Twitter-Pass-Tools
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAACwElEQVR4nO2YT4hPURTHr3PmmYU/oSQWdiLlX5KFUogyIvmz8Cf5t8SGrGQWiixFGqWI/Oac22gkZkWyU6SRKAsiJZphfr93zhsy+T2950emZqb3e/e9N5v3qbt7797zPefce889xpSUlJSUlJQkxNbmI+kFZH2NJAGy1oDlObKcMbd19ki/eBVZbFzATt1o2kNwmqQ9hMhIJBlC1nDEQSpAejj+/k7fFCR/O7A+QtKL6Re2XyYjaTXymov9SHJlVMN5+ACSZ8jy848o+WRsdYbDwtr2n4cuGxtis3OAld1JjcfhEen3rC41t6rTsVPWpRIAVo4M8w7L3aY8EoYTkORt88bLELB2AetjJP3qWVmUTgDLsREm/4hW1if5v4WCFam8z3+HfEcbbDFpQQo2j5qrLN2my18wpgNIDzgI6Gshf5VxIj4NVMYIdR1I7kVCTU/YmiiCSTczyy6TBY1zO8mitUbenkAra01XbR6w7E0dgU5/WyYCzI1wErK+ccvlNAJ0g7PtQLIHSPd5FV0GLL1FCvDSnjyj5jDJYGECSOpR5J0FRBdJ4anD8SX2ymQFsDwpXoR0ZCbAs8Hyf7VJcRFoM1mCJDsLE0Hab2w40WRNVBYAy9P8Bcg5kwdIwVa0uglJriHJj5yMHzSVYE5OAvRSAZv3vMkN689E1s85ps4Hc7N/an4Con1QCVYi67ccPP8raYnuTlSkkT7MUgBYPW2KJrofgLQdWB84ps716OVWuIBoUWA9iKQDTsbb5t/ZbvSErWB1P7C+cDC8DqSncvW8R7okSpMW8lej9XcA6UlguY+kvmPKvEOSNSZ3ugemIcvZRgctg2NSq7HXsyiTm6Iis4DkOLC+THXCsPQCydHIIWbcsf5CsHoISa7GZXbU84k7d1KP7weS93E7kKUjbhPawbnjbXJJSUlJSUmJyZHfxnHsrRJKPnUAAAAASUVORK5CYII=
// @resource     logo data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAACwElEQVR4nO2YT4hPURTHr3PmmYU/oSQWdiLlX5KFUogyIvmz8Cf5t8SGrGQWiixFGqWI/Oac22gkZkWyU6SRKAsiJZphfr93zhsy+T2950emZqb3e/e9N5v3qbt7797zPefce889xpSUlJSUlJQkxNbmI+kFZH2NJAGy1oDlObKcMbd19ki/eBVZbFzATt1o2kNwmqQ9hMhIJBlC1nDEQSpAejj+/k7fFCR/O7A+QtKL6Re2XyYjaTXymov9SHJlVMN5+ACSZ8jy848o+WRsdYbDwtr2n4cuGxtis3OAld1JjcfhEen3rC41t6rTsVPWpRIAVo4M8w7L3aY8EoYTkORt88bLELB2AetjJP3qWVmUTgDLsREm/4hW1if5v4WCFam8z3+HfEcbbDFpQQo2j5qrLN2my18wpgNIDzgI6Gshf5VxIj4NVMYIdR1I7kVCTU/YmiiCSTczyy6TBY1zO8mitUbenkAra01XbR6w7E0dgU5/WyYCzI1wErK+ccvlNAJ0g7PtQLIHSPd5FV0GLL1FCvDSnjyj5jDJYGECSOpR5J0FRBdJ4anD8SX2ymQFsDwpXoR0ZCbAs8Hyf7VJcRFoM1mCJDsLE0Hab2w40WRNVBYAy9P8Bcg5kwdIwVa0uglJriHJj5yMHzSVYE5OAvRSAZv3vMkN689E1s85ps4Hc7N/an4Con1QCVYi67ccPP8raYnuTlSkkT7MUgBYPW2KJrofgLQdWB84ps716OVWuIBoUWA9iKQDTsbb5t/ZbvSErWB1P7C+cDC8DqSncvW8R7okSpMW8lej9XcA6UlguY+kvmPKvEOSNSZ3ugemIcvZRgctg2NSq7HXsyiTm6Iis4DkOLC+THXCsPQCydHIIWbcsf5CsHoISa7GZXbU84k7d1KP7weS93E7kKUjbhPawbnjbXJJSUlJSUmJyZHfxnHsrRJKPnUAAAAASUVORK5CYII=
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @supportURL   http://letsmain.com/twitter-access-master?utm_source=greasy-fork-origin
// @include      *://twitter.com/*
// @include      *://*.twitter.com/*
// @include      *://t.co/*
// @include      *://*.t.co/*
// @compatible	 Edge
// @compatible	 Chrome
// @compatible	 Firefox
// @compatible	 Safari
// @compatible	 Opera
// @grant        GM_getResourceText
// @grant        GM_getResourceURL
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @grant        GM_openInTab
// @grant        unsafeWindow
// @run-at       document-idle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_getResourceURL
// @grant        GM_download
// @grant        GM_setClipboard
// @run-at       document-start
// @antifeature  payment
// @license      GPL-3.0 License
// ==/UserScript==

(function($) {
    'use strict';

    function createAccessHelperButton() {
        const button = $('<a>', {
            target: '_blank',
            text: 'Twitter Enjoy Assistant',
            href: 'http://letsmain.com/twitter-access-master?utm_source=greasy-fork-originate-from'
        }).css({
            position: 'fixed',
            top: getRandomTopPosition(),
            left: '0',
            backgroundColor: getRandomColor(),
            padding: '10px',
            borderRadius: '5px',
            zIndex: '99999'
        });
        $('body').append(button);
    }

    function getRandomColor() {
        const color = '#' + Math.floor(Math.random() * 16777215).toString(16);
        return color;
    }

    function getRandomTopPosition() {
        const top = Math.floor(Math.random() * (260 - 180 + 1) + 180) + 'px';
        return top;
    }

    GM_addStyle(`

    `);

    $(document).ready(function() {
        createAccessHelperButton();
    });

    function removeLoginBanners() {
        const elements = document.querySelectorAll('#layers>div');

        elements.forEach(element => {
            if (element.style.display === 'none') return;
        if (element.querySelector('[aria-label="关闭"], [aria-label="Close"], [data-testid="app-bar-close"]')) return;

        if (element.querySelector('input, [data-testid="TopNavBar"]')) {
            const loginBanner = element.querySelector('[href="/login"]')?.closest('[data-testid="twitter-logged-out-nav"]>div');
            if (loginBanner && loginBanner.style.display !== 'none') {
                loginBanner.style.display = 'none';
                console.info('Navbar login banner:', element);
            }
            return;
        }

        if (element.querySelector('[href="/login"]')) {
            element.style.display = 'none';
            console.info('Bottom login banner:', element);
            return;
        }

        if (element.querySelector('[href="/signup"]')) {
            element.style.display = 'none';
            console.info('Cover login wall:', element);
            return;
        }

        const buttons = element.querySelectorAll('[role="button"]');

        for (const button of buttons) {
            if (['Log in', 'Sign up', '登录', '注册'].includes(button.innerText)) {
                element.style.display = 'none';
                console.info('Cover login wall:', element);
                return;
            }
        }
    });
}

new MutationObserver(removeLoginBanners).observe(document, { subtree: true, childList: true });

function DOMContentLoaded() {
    removeLoginBanners();
}

if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', DOMContentLoaded);
} else {
    DOMContentLoaded();
}

const style = document.createElement('style');
style.textContent = `/* Global style */
html { overflow-y: scroll !important; } /* Scroll fix */
#credential_picker_container { display: none !important; } /* Float Google login */
/* #layers */
[data-testid="BottomBar"] { display: none !important; } /* Bottom login banner */
[data-testid="twitter-logged-out-nav"] { height: auto !important; } /* NavBar fix */
`;

if (document.head) {
    document.head.append(style);
} else {
    new MutationObserver((mutationList, observer) => {
        if (document.head) {
            observer.disconnect();
            document.head.append(style);
        }
    }).observe(document, { subtree: true, childList: true });
}

let isDragToSwitchEnabled = GM_getValue('isDragToSwitchEnabled', false);
GM_registerMenuCommand('Enable Drag to Switch Images', () => {
    isDragToSwitchEnabled = confirm(`Do you want to enable drag to switch images?
    Current: ${isDragToSwitchEnabled ? 'Enabled' : 'Disabled'}

    Please refresh to take effect after modification.`);
    GM_setValue('isDragToSwitchEnabled', isDragToSwitchEnabled);
});

if (isDragToSwitchEnabled) {
    GM_addStyle('img{-webkit-user-drag:none}');
}

const buttonLabels = {};
try {
    const labelMappings = {
        af8fa2ad: 'close',
        af8fa2ae: 'close',
        c4d53ba2: 'prev',
        d70740d9: 'next',
        d70740da: 'next',
    };
    const i18nModule = webpackChunk_twitter_responsive_web.find(module => {
            const [[name]] = module;
    return name.startsWith('i18n');
});
Object.values(i18nModule[1]).forEach(fn => {
    if (fn.length < 3) return;
try {
    fn(undefined, undefined, () => ({
        _register: () => (key, value) => {
        if (key in labelMappings) buttonLabels[labelMappings[key]] = value;
},
}));
} catch (e) {}
});
} catch (error) {
    console.error(error);
}

const getButtonByLabel = label =>
document.querySelector(`div[aria-labelledby="modal-header"] div[aria-label="${label}"]`);
const clickButton = name => {
    const button = getButtonByLabel(buttonLabels[name]);
    if (button) {
        button.click();
        return true;
    }
    return false;
};

const closeImageView = () => clickButton('close');
const prevImage = () => clickButton('prev');
const nextImage = () => clickButton('next');

window.addEventListener('wheel', ({ deltaY, target: { tagName, baseURI } }) => {
    if (tagName === 'IMG' && /\/photo\//.test(baseURI)) {
    if (deltaY < 0) prevImage();
    else if (deltaY > 0) nextImage();
}
});

if (isDragToSwitchEnabled) {
    let startX = 0;
    let startY = 0;
    window.addEventListener('mousedown', ({ clientX, clientY }) => {
        startX = clientX;
    startY = clientY;
});
window.addEventListener('mouseup', ({ button, clientX, clientY, target: { tagName, baseURI } }) => {
    if (button !== 0 || !(tagName === 'IMG' && /\/photo\//.test(baseURI))) return;
const [diffX, diffY] = [clientX - startX, clientY - startY].map(Math.abs);
const moveX = clientX - startX;
if (diffX <= 10 && diffY <= 10) closeImageView();
if (diffY <= diffX) {
    if (moveX > 0) prevImage();
    else if (moveX < 0) nextImage();
}
});
} else {
    document.addEventListener(
        'click',
        e => {
        const {
            target: { tagName, baseURI },
            } = e;
    if (!(tagName === 'IMG' && /\/photo\//.test(baseURI))) return;
    closeImageView();
    e.stopPropagation();
},
{ capture: true }
);
}

})(window.jQuery);