Guest User

Untitled

a guest
Jun 17th, 2025
12
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         RG Tweet Video Remover with Catalog
  3. // @namespace    http://tampermonkey.net/
  4. // @version      1.1
  5. // @description  Floating RG button removes tweet_video posts, catalogs URLs, and copies them via 📋 button
  6. // @author       you
  7. // @match        *://nitter.privacydev.net/*
  8. // @match        *://nitter.poast.org/*
  9. // @match        *://xcancel.com/*
  10. // @match        *://lightbrd.com/*
  11. // @match        *://nitter.net/*
  12. // @grant        GM_setClipboard
  13. // ==/UserScript==
  14.  
  15. (function() {
  16.     'use strict';
  17.  
  18.     let isActive = false;
  19.     let observer = null;
  20.     let deletedUrls = new Set();
  21.  
  22.     function isDarkMode() {
  23.         return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
  24.     }
  25.  
  26.     function getStatusUrl(item) {
  27.         // Try to find the status link in the tweet/post element
  28.         let aList = item.querySelectorAll('a[href*="/status/"]');
  29.         for (let a of aList) {
  30.             let match = a.href.match(/https:\/\/(twitter|x)\.com\/[^/]+\/status\/\d+/);
  31.             if (match) return match;
  32.         }
  33.         return null;
  34.     }
  35.  
  36.     function removeRelevantPosts() {
  37.         const items = document.querySelectorAll('.timeline-item, article, [data-testid="tweet"]');
  38.         items.forEach(function(item) {
  39.             if (
  40.                 item.innerHTML.includes('video.twimg.com%2Ftweet_video%2F') ||
  41.                 item.innerHTML.includes('video.twimg.com/tweet_video/')
  42.             ) {
  43.                 let url = getStatusUrl(item);
  44.                 if (url && !deletedUrls.has(url)) {
  45.                     deletedUrls.add(url);
  46.                     addUrlToCatalog(url);
  47.                 }
  48.                 item.remove();
  49.             }
  50.         });
  51.     }
  52.  
  53.     // --- UI Elements ---
  54.  
  55.     // RG Toggle Button
  56.     let fabButton = document.createElement('button');
  57.     fabButton.textContent = "RG ";
  58.     fabButton.setAttribute('aria-label', 'Remove GIF posts');
  59.     fabButton.title = 'RG Inactive: Click to activate';
  60.     fabButton.style.position = 'fixed';
  61.     fabButton.style.bottom = '24px';
  62.     fabButton.style.left = '116px';
  63.     fabButton.style.zIndex = '99999';
  64.     fabButton.style.fontSize = '18px';
  65.     fabButton.style.padding = '10px 18px';
  66.     fabButton.style.borderRadius = '24px';
  67.     fabButton.style.border = '1.5px solid #ccc';
  68.     fabButton.style.boxShadow = '0 4px 24px rgba(0,0,0,0.11)';
  69.     fabButton.style.fontWeight = 'bold';
  70.     fabButton.style.cursor = 'pointer';
  71.     fabButton.style.transition = 'background 0.2s,color 0.2s';
  72.     fabButton.style.background = isDarkMode() ? '#222' : '#fff';
  73.     fabButton.style.color = isDarkMode() ? '#fff' : '#005940';
  74.     fabButton.style.userSelect = 'none';
  75.  
  76.     document.body.appendChild(fabButton);
  77.  
  78.     // Catalog UI (collapsible)
  79.     let catalogUI = document.createElement('div');
  80.     catalogUI.style.position = 'fixed';
  81.     catalogUI.style.left = '116px';
  82.     catalogUI.style.bottom = '76px';
  83.     catalogUI.style.zIndex = '99999';
  84.     catalogUI.style.minWidth = '272px';
  85.     catalogUI.style.maxWidth = '330px';
  86.     catalogUI.style.maxHeight = '300px';
  87.     catalogUI.style.overflowY = 'auto';
  88.     catalogUI.style.background = isDarkMode() ? '#232629' : '#fbfbfb';
  89.     catalogUI.style.color = isDarkMode() ? '#fff' : '#212121';
  90.     catalogUI.style.border = '1.5px solid #ccc';
  91.     catalogUI.style.border = '1.5px solid #ccc';
  92.     catalogUI.style.borderRadius = '12px';
  93.     catalogUI.style.boxShadow = '0 4px 24px rgba(0,0,0,0.12)';
  94.     catalogUI.style.padding = '10px 10px 8px 12px';
  95.     catalogUI.style.fontSize = '15px';
  96.     catalogUI.style.display = 'flex';
  97.     catalogUI.style.flexDirection = 'column';
  98.     catalogUI.style.gap = '7px';
  99.     catalogUI.style.userSelect = 'text';
  100.  
  101.     // Collapsible header
  102.     const catalogHeader = document.createElement('div');
  103.     catalogHeader.style.display = 'flex';
  104.     catalogHeader.style.justifyContent = 'space-between';
  105.     catalogHeader.style.alignItems = 'center';
  106.     catalogHeader.style.cursor = 'pointer';
  107.     catalogHeader.style.paddingBottom = '6px';
  108.     catalogHeader.style.borderBottom = '1px solid #ccc';
  109.  
  110.     const headerTitle = document.createElement('span');
  111.     headerTitle.textContent = '🗂️ Removed Status URLs';
  112.  
  113.     const collapseBtn = document.createElement('span');
  114.     collapseBtn.textContent = '▾'; // Collapsed: '▸', Expanded: '▾'
  115.     collapseBtn.style.fontSize = '14px';
  116.     collapseBtn.style.marginLeft = '7px';
  117.  
  118.     catalogHeader.appendChild(headerTitle);
  119.     catalogHeader.appendChild(collapseBtn);
  120.  
  121.     // URL List
  122.     const urlList = document.createElement('div');
  123.     urlList.id = 'rg-url-list';
  124.     urlList.style.margin = '7px 0 0 0';
  125.     urlList.style.display = 'block';
  126.  
  127.     // Copy button
  128.     const copyBtn = document.createElement('button');
  129.     copyBtn.textContent = '📋';
  130.     copyBtn.title = 'Copy all URLs';
  131.     copyBtn.style.margin = '3px 0 0 3px';
  132.     copyBtn.style.border = '1px solid #bbb';
  133.     copyBtn.style.borderRadius = '6px';
  134.     copyBtn.style.padding = '3px 7px';
  135.     copyBtn.style.background = isDarkMode() ? '#333' : '#eee';
  136.     copyBtn.style.color = isDarkMode() ? '#fff' : '#222';
  137.     copyBtn.style.fontSize = '15px';
  138.     copyBtn.style.cursor = 'pointer';
  139.     copyBtn.style.alignSelf = 'flex-start';
  140.     copyBtn.style.transition = 'background 0.15s';
  141.  
  142.     copyBtn.addEventListener('click', function () {
  143.         const allUrls = Array.from(deletedUrls).join('\n');
  144.         if (typeof GM_setClipboard !== 'undefined') {
  145.             GM_setClipboard(allUrls, { type: 'text', mimetype: 'text/plain' });
  146.         } else if (navigator.clipboard) {
  147.             navigator.clipboard.writeText(allUrls);
  148.         }
  149.         copyBtn.textContent = '✅';
  150.         setTimeout(() => (copyBtn.textContent = '📋'), 900);
  151.     });
  152.  
  153.     // Collapse functionality
  154.     let collapsed = false;
  155.     catalogHeader.addEventListener('click', function () {
  156.         collapsed = !collapsed;
  157.         urlList.style.display = collapsed ? 'none' : 'block';
  158.         copyBtn.style.display = collapsed ? 'none' : 'inline-block';
  159.         collapseBtn.textContent = collapsed ? '▸' : '▾';
  160.     });
  161.  
  162.     // Add children to catalog UI
  163.     catalogUI.appendChild(catalogHeader);
  164.     catalogUI.appendChild(copyBtn);
  165.     catalogUI.appendChild(urlList);
  166.     document.body.appendChild(catalogUI);
  167.  
  168.     function addUrlToCatalog(url) {
  169.         if (document.getElementById('rg-url-' + btoa(url))) return;
  170.         const urlBox = document.createElement('div');
  171.         urlBox.textContent = url;
  172.         urlBox.style.background = isDarkMode() ? '#181c1f' : '#f2f2f4';
  173.         urlBox.style.borderRadius = '4px';
  174.         urlBox.style.padding = '4px 7px';
  175.         urlBox.style.margin = '2px 0';
  176.         urlBox.style.wordBreak = 'break-all';
  177.         urlBox.id = 'rg-url-' + btoa(url);
  178.         urlList.appendChild(urlBox);
  179.     }
  180.  
  181.     function refreshCatalogTheme() {
  182.         catalogUI.style.background = isDarkMode() ? '#232629' : '#fbfbfb';
  183.         catalogUI.style.color = isDarkMode() ? '#fff' : '#212121';
  184.         copyBtn.style.background = isDarkMode() ? '#333' : '#eee';
  185.         copyBtn.style.color = isDarkMode() ? '#fff' : '#222';
  186.         urlList.querySelectorAll('div').forEach(el => {
  187.             el.style.background = isDarkMode() ? '#181c1f' : '#f2f2f4';
  188.         });
  189.         fabButton.style.background = isDarkMode() ? (isActive ? '#048848':'#222') : (isActive ? '#23be78':'#fff');
  190.         fabButton.style.color = isDarkMode() ? '#fff' : (isActive ? '#fff' : '#005940');
  191.     }
  192.  
  193.     // The RG button logic
  194.     function setButtonActive(active) {
  195.         if(active){
  196.             removeRelevantPosts();
  197.             observer = new MutationObserver(() => {
  198.                 removeRelevantPosts();
  199.             });
  200.             observer.observe(document.body, {childList:true, subtree:true});
  201.             fabButton.style.background = isDarkMode() ? '#048848' : '#23be78';
  202.             fabButton.style.color = '#fff';
  203.             fabButton.title = 'RG Active: Hides tweet_video posts';
  204.         } else {
  205.             if(observer) observer.disconnect();
  206.             observer = null;
  207.             fabButton.style.background = isDarkMode() ? '#222' : '#fff';
  208.             fabButton.style.color = isDarkMode() ? '#fff' : '#005940';
  209.             fabButton.title = 'RG Inactive: Click to activate';
  210.         }
  211.         refreshCatalogTheme();
  212.     }
  213.  
  214.     fabButton.addEventListener('click', function() {
  215.         isActive = !isActive;
  216.         setButtonActive(isActive);
  217.     });
  218.  
  219.     // On page reload
  220.     window.addEventListener("pageshow",function(){
  221.         setButtonActive(isActive);
  222.     });
  223.  
  224.     // Update on dark/light change
  225.     window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', refreshCatalogTheme);
  226.  
  227.     // Don't let the catalog or button block pointer events to stuff underneath
  228.     fabButton.style.pointerEvents = 'auto';
  229.     catalogUI.style.pointerEvents = 'auto';
  230.  
  231.     // Extra: give RG button and catalog unique IDs for styling/debug
  232.     fabButton.id = '__rg_fab_button';
  233.     catalogUI.id = '__rg_catalog_ui';
  234.  
  235. })();
Advertisement
Add Comment
Please, Sign In to add comment