// ==UserScript== // @name Twitterᴾˡᵘˢ (View Twitter Origin Images) // @name:zh-TW Twitterᴾˡᵘˢ (檢視Twitter原始圖檔) // @name:zh-CN Twitterᴾˡᵘˢ (检视Twitter原始图档) // @namespace https://greasyfork.org // @version 0.1.0 // @description Enhance the Twitter user experience. The main features include replacing images with the original quality and getting the original image URL by right-clicking, and hiding posts that contain specific hashtags or exceed a set number. // @description:zh-TW 加強使用推特的體驗。主要功能包含圖片更換為原始畫質並從右鍵取得原始圖片網址、當貼文包含指定hashtag或超過指定數量則隱藏該貼文。 // @description:zh-CN 加强使用推特的体验。主要功能包含图片更换为原始画质并从右键取得原始图片网址、当贴文包含指定hashtag或超过指定数量则隐藏该贴文。 // @author Pixmi // @icon https://www.google.com/s2/favicons?sz=64&domain=twitter.com // @match https://twitter.com/* // @match https://pbs.twimg.com/media/* // @license MIT // @grant GM_setValue // @grant GM_getValue // @downloadURL none // ==/UserScript== (function () { 'use strict'; // Hide the post if the hashtag exceeds the set number. (If set to 0, it will not be enabled) GM_setValue('MAX_HASHTAGS', 20); // Hide the post if it contains the following hashtag. (Please include "#" and separate using commas) GM_setValue('OUT_HASHTAGS', ['#tag1', '#tag2']) let URL = window.location.href; // If browsing an image URL, change it to obtain the original quality. if (URL.match(/https:\/\/pbs\.twimg\.com\/media\/([a-zA-Z0-9\-\_]+)(\?format=|.)(jpg|jpeg|png)/) && !URL.includes('?name=orig')) { if (URL.indexOf('?format=') > 0) { URL = URL.replace('?format=', '.'); } if (URL.match(/\&name=(\w+)/)) { URL = URL.replace(/\&name=(\w+)/g, '?name=orig'); } else { URL = `${URL}?name=orig`; } window.location.replace(URL); } // 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'); if (rootnode) { let callback = function (mutationsList, observer) { for (let mutation of mutationsList) { let target = mutation.target; // image class name if (target.className.includes('css-1dbjc4n')) { // hashtag check let hashtags = Array.from(target.querySelectorAll('.css-901oao > .r-18u37iz'), tag => tag.textContent); let hideCheck = []; if (hashtags.length && target.nodeName == 'ARTICLE') { // MAX_HASHTAGS must be greater than 0. if (MAX_HASHTAGS > 0) hideCheck.push(hashtags.length >= MAX_HASHTAGS); hideCheck.push(hashtags.some(tag => OUT_HASHTAGS.find(item => item == tag))); if (hideCheck.some(item => item === true)) { target.closest('.css-1dbjc4n.r-1igl3o0').style.display = 'none'; target.remove(); continue; } } let images = target.getElementsByTagName('img'); for (let i = 0; i < images.length; i++) { let imgSrc = images[i].src; if (imgSrc.includes('https://pbs.twimg.com/media/') && !imgSrc.match(/name=orig/)) { images[i].src = imgSrc.replace('?format=', '.').replace(/&name=(\w+)/g, '?name=orig'); } } } } }; const observeConfig = { attributes: true, childList: true, subtree: true }; const observer = new MutationObserver(callback); observer.observe(document.body, observeConfig); } } })();