Twitterᴾˡᵘˢ

Enhance Twitter user experience. Load images in original quality, remove tweets that contain specific hashtags or exceed the maximum limit.

2023-11-22 या दिनांकाला. सर्वात नवीन आवृत्ती पाहा.

// ==UserScript==
// @name        Twitterᴾˡᵘˢ
// @name:zh-TW  Twitterᴾˡᵘˢ
// @name:zh-CN  Twitterᴾˡᵘˢ
// @name:ja     Twitterᴾˡᵘˢ
// @namespace   https://greasyfork.org
// @version     0.3.0
// @description         Enhance Twitter user experience. Load images in original quality, remove tweets that contain specific hashtags or exceed the maximum limit.
// @description:zh-TW   增強Twitter使用者體驗。讀取原始畫質的圖片,移除包含特定Hashtag或超過最大限制的推文。
// @description:zh-CN   增强Twitter使用者体验。读取原始画质的图片,移除包含特定Hashtag或超过最大限制的推文。
// @description:ja      Twitterのユーザー体験を向上させます。元の品質で画像をロードし、特定のハッシュタグを含むまたは最大限度を超えるツイートを非表示にします。
// @author      Pixmi
// @icon        https://www.google.com/s2/favicons?sz=64&domain=twitter.com
// @match       https://twitter.com/*
// @match       https://mobile.twitter.com/*
// @match       https://pbs.twimg.com/media/*
// @license     AGPL-3.0-or-later
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_addStyle
// ==/UserScript==
// Hide the post if the hashtag exceeds the set number. (If set to 0, it will not be enabled)
if (GM_getValue('MAX_HASHTAGS') == undefined) { GM_setValue('MAX_HASHTAGS', 20); }
// Hide the post if it contains the following hashtag. (Please include "#" and separate using commas)
if (GM_getValue('OUT_HASHTAGS') == undefined) { GM_setValue('OUT_HASHTAGS', '#tag1,#tag2'); }
// Change OUT_HASHTAGS type to string
if (typeof GM_getValue('OUT_HASHTAGS') == 'object') { GM_setValue('OUT_HASHTAGS', GM_getValue('OUT_HASHTAGS').join(',')); }

(function () {
    'use strict';
    const URL = window.location.href;
    const twimg = URL.match(/https:\/\/(pbs\.twimg\.com\/media\/[a-zA-Z0-9\-\_]+)(\?format=|.)(jpg|jpeg|png|webp)/);
    // browsing an image URL
    if (twimg) {
        // webp change to jpg
        if (twimg[3] == 'webp') twimg[3] = 'jpg';
        // change it to obtain the original quality.
        if (twimg[2] == '?format=' || !/name=orig/.test(URL)) {
            window.location.replace(`https://${twimg[1]}.${twimg[3]}?name=orig`);
        }
    }
    // if browsing tweets, activate the observer.
    if (URL.includes('twitter.com')) {
        const rootmatch = document.evaluate('//div[@id="react-root"]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
        const rootnode = rootmatch.singleNodeValue;
        const MAX_HASHTAGS = GM_getValue('MAX_HASHTAGS');
        const OUT_HASHTAGS = GM_getValue('OUT_HASHTAGS').split(',');
        if (rootnode) {
            const callback = (mutationsList, observer) => {
                for (let mutation of mutationsList) {
                    let target = mutation.target;
                    if (target.nodeName !== 'ARTICLE' || !target.classList.contains('css-175oi2r')) continue;
                    let hashtags = Array.from(target.querySelectorAll('.css-1rynq56 > .r-18u37iz'), tag => tag.textContent);
                    let hideCheck = false;
                    if (hashtags.length) {
                        if (MAX_HASHTAGS > 0 &&hashtags.length >= MAX_HASHTAGS) hideCheck = true;
                        if (hashtags.some(tag => OUT_HASHTAGS.find(item => item == tag))) hideCheck = true;
                        if (hideCheck) {
                            target.closest('div[data-testid="cellInnerDiv"] > div').style.display = 'none';
                            target.remove();
                            continue;
                        }
                    }
                    let images = target.getElementsByTagName('img');
                    if (!images.length) continue;
                    for (const image of images) {
                        let match = image.src.match(/https:\/\/(pbs\.twimg\.com\/media\/[a-zA-Z0-9\-\_]+)(\?format=|.)(jpg|jpeg|png|webp)/);
                        if (!match) continue;
                        // Image url change to original quality.
                        if (match[3] == 'webp') match[3] = 'jpg';
                        if (match[2] == '?format=' || !/name=orig/.test(image.src)) {
                            image.src = `https://${match[1]}.${match[3]}?name=orig`;
                        }
                    }
                }
            };
            const observeConfig = {
                attributes: true,
                childList: true,
                subtree: true
            };
            const observer = new MutationObserver(callback);

            observer.observe(document.body, observeConfig);
        }
    }
})();