Guest User

X/Twitter Media Tab Options Filter Images or Videos

a guest
Jun 14th, 2025
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 7.79 KB | Source Code | 0 0
  1. // ==UserScript==
  2. // @name         X.com Media Filter
  3. // @namespace    http://tampermonkey.net/
  4. // @version      1.0
  5. // @description  Filter X.com media tab to show only images or only videos
  6. // @author       You
  7. // @match        https://x.com/*/media
  8. // @match        https://twitter.com/*/media
  9. // @grant        none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13.     'use strict';
  14.  
  15.     // Create filter buttons
  16.     function createFilterButtons() {
  17.         const filterContainer = document.createElement('div');
  18.         filterContainer.id = 'media-filter-controls';
  19.         filterContainer.style.cssText = `
  20.             position: fixed;
  21.             top: 20px;
  22.             right: 20px;
  23.             z-index: 9999;
  24.             background: rgba(0, 0, 0, 0.8);
  25.             border-radius: 12px;
  26.             padding: 12px;
  27.             display: flex;
  28.             gap: 8px;
  29.             backdrop-filter: blur(10px);
  30.         `;
  31.  
  32.         const buttonStyle = `
  33.             padding: 8px 16px;
  34.             border: none;
  35.             border-radius: 8px;
  36.             background: #1d9bf0;
  37.             color: white;
  38.             cursor: pointer;
  39.             font-size: 14px;
  40.             font-weight: 600;
  41.             transition: all 0.2s;
  42.         `;
  43.  
  44.         const activeButtonStyle = `
  45.             background: #1a8cd8;
  46.             transform: scale(0.95);
  47.         `;
  48.  
  49.         // All button
  50.         const allBtn = document.createElement('button');
  51.         allBtn.textContent = 'All';
  52.         allBtn.style.cssText = buttonStyle;
  53.         allBtn.onclick = () => filterMedia('all');
  54.  
  55.         // Images only button
  56.         const imagesBtn = document.createElement('button');
  57.         imagesBtn.textContent = 'Images';
  58.         imagesBtn.style.cssText = buttonStyle;
  59.         imagesBtn.onclick = () => filterMedia('images');
  60.  
  61.         // Videos only button
  62.         const videosBtn = document.createElement('button');
  63.         videosBtn.textContent = 'Videos';
  64.         videosBtn.style.cssText = buttonStyle;
  65.         videosBtn.onclick = () => filterMedia('videos');
  66.  
  67.         filterContainer.appendChild(allBtn);
  68.         filterContainer.appendChild(imagesBtn);
  69.         filterContainer.appendChild(videosBtn);
  70.  
  71.         document.body.appendChild(filterContainer);
  72.  
  73.         return { allBtn, imagesBtn, videosBtn };
  74.     }
  75.  
  76.     // Filter media based on type
  77.     function filterMedia(type) {
  78.         // Update button states
  79.         const buttons = document.querySelectorAll('#media-filter-controls button');
  80.         buttons.forEach(btn => {
  81.             btn.style.background = '#1d9bf0';
  82.             btn.style.transform = 'none';
  83.         });
  84.  
  85.         const activeBtn = document.querySelector(`#media-filter-controls button:nth-child(${
  86.             type === 'all' ? '1' : type === 'images' ? '2' : '3'
  87.         })`);
  88.         if (activeBtn) {
  89.             activeBtn.style.background = '#1a8cd8';
  90.             activeBtn.style.transform = 'scale(0.95)';
  91.         }
  92.  
  93.         // Find all media items - multiple selectors for different X.com layouts
  94.         const mediaSelectors = [
  95.             '[data-testid="cellInnerDiv"]',
  96.             '[role="gridcell"]',
  97.             'div[style*="padding-bottom"]', // Common for media grid items
  98.             'a[href*="/photo/"]',
  99.             'a[href*="/video/"]'
  100.         ];
  101.  
  102.         let mediaItems = [];
  103.         for (const selector of mediaSelectors) {
  104.             const items = document.querySelectorAll(selector);
  105.             if (items.length > 0) {
  106.                 mediaItems = Array.from(items);
  107.                 break;
  108.             }
  109.         }
  110.  
  111.         // If no items found with standard selectors, try broader approach
  112.         if (mediaItems.length === 0) {
  113.             // Look for containers that likely contain media
  114.             const possibleContainers = document.querySelectorAll('div[style*="padding-bottom"], div[data-testid], a[href*="/status/"]');
  115.             mediaItems = Array.from(possibleContainers).filter(item => {
  116.                 return item.querySelector('img, video') ||
  117.                        item.innerHTML.includes('video') ||
  118.                        item.innerHTML.includes('photo');
  119.             });
  120.         }
  121.  
  122.         mediaItems.forEach(item => {
  123.             const isVideo = isVideoItem(item);
  124.             const isImage = isImageItem(item);
  125.  
  126.             switch(type) {
  127.                 case 'all':
  128.                     item.style.display = '';
  129.                     break;
  130.                 case 'images':
  131.                     item.style.display = isImage && !isVideo ? '' : 'none';
  132.                     break;
  133.                 case 'videos':
  134.                     item.style.display = isVideo ? '' : 'none';
  135.                     break;
  136.             }
  137.         });
  138.  
  139.         console.log(`Filtered ${mediaItems.length} items for type: ${type}`);
  140.     }
  141.  
  142.     // Check if item contains video
  143.     function isVideoItem(item) {
  144.         // Multiple ways to detect videos
  145.         return item.querySelector('video') ||
  146.                item.querySelector('[data-testid*="video"]') ||
  147.                item.querySelector('.PlayableMedia-player') ||
  148.                item.innerHTML.includes('video') ||
  149.                item.href?.includes('/video/') ||
  150.                item.querySelector('svg[aria-label*="Play"]') ||
  151.                item.querySelector('[aria-label*="video"]') ||
  152.                item.querySelector('[role="button"][aria-label*="Play"]');
  153.     }
  154.  
  155.     // Check if item contains image
  156.     function isImageItem(item) {
  157.         // Multiple ways to detect images
  158.         return item.querySelector('img:not([alt*="avatar"]):not([alt*="profile"])') ||
  159.                item.href?.includes('/photo/') ||
  160.                item.querySelector('[data-testid*="image"]') ||
  161.                item.querySelector('[aria-label*="image"]');
  162.     }
  163.  
  164.     // Initialize when page loads
  165.     function init() {
  166.         // Wait for page to load
  167.         setTimeout(() => {
  168.             if (window.location.pathname.includes('/media')) {
  169.                 const buttons = createFilterButtons();
  170.                 console.log('X.com Media Filter initialized');
  171.                
  172.                 // Re-run filter when new content loads (infinite scroll)
  173.                 const observer = new MutationObserver(() => {
  174.                     // Debounce to avoid excessive calls
  175.                     clearTimeout(window.mediaFilterTimeout);
  176.                     window.mediaFilterTimeout = setTimeout(() => {
  177.                         const activeFilter = getActiveFilter();
  178.                         if (activeFilter !== 'all') {
  179.                             filterMedia(activeFilter);
  180.                         }
  181.                     }, 500);
  182.                 });
  183.                
  184.                 observer.observe(document.body, {
  185.                     childList: true,
  186.                     subtree: true
  187.                 });
  188.             }
  189.         }, 2000);
  190.     }
  191.  
  192.     // Get currently active filter
  193.     function getActiveFilter() {
  194.         const buttons = document.querySelectorAll('#media-filter-controls button');
  195.         for (let i = 0; i < buttons.length; i++) {
  196.             if (buttons[i].style.background === 'rgb(26, 140, 216)') {
  197.                 return ['all', 'images', 'videos'][i];
  198.             }
  199.         }
  200.         return 'all';
  201.     }
  202.  
  203.     // Handle navigation changes (SPA)
  204.     let currentUrl = window.location.href;
  205.     const checkUrlChange = () => {
  206.         if (window.location.href !== currentUrl) {
  207.             currentUrl = window.location.href;
  208.             // Remove old controls
  209.             const oldControls = document.getElementById('media-filter-controls');
  210.             if (oldControls) oldControls.remove();
  211.             // Reinitialize if on media page
  212.             init();
  213.         }
  214.     };
  215.  
  216.     // Check for URL changes every second
  217.     setInterval(checkUrlChange, 1000);
  218.  
  219.     // Initial load
  220.     init();
  221.  
  222. })();
Add Comment
Please, Sign In to add comment