Guest User

Untitled

a guest
Jul 10th, 2025
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.34 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Twitter/X User Media Tab Deduplicator
  3. // @namespace https://x.com
  4. // @version 1.0
  5. // @description Hide all duplicate media in user profiles media tab
  6. // @author KBD99
  7. // @match https://x.com/*/media*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. let dedupEnabled = true;
  15. const HASH_KEY = 'twitterMediaHashes';
  16. let seenHashes = JSON.parse(localStorage.getItem(HASH_KEY) || '{}');
  17.  
  18. // UI Toggle Button
  19. const toggleButton = document.createElement('button');
  20. toggleButton.textContent = 'Dedup ON';
  21. Object.assign(toggleButton.style, {
  22. position: 'fixed',
  23. top: '10px',
  24. right: '10px',
  25. zIndex: 9999,
  26. padding: '6px',
  27. fontSize: '10px',
  28. backgroundColor: '#1da1f2',
  29. color: 'white',
  30. border: 'none',
  31. borderRadius: '3px',
  32. cursor: 'pointer',
  33. });
  34. toggleButton.onclick = () => {
  35. dedupEnabled = !dedupEnabled;
  36. toggleButton.textContent = dedupEnabled ? 'Dedup ON' : 'Dedup OFF';
  37. if (dedupEnabled) runDeduplication();
  38. };
  39.  
  40. // Clear Cache Button
  41. const clearButton = document.createElement('button');
  42. clearButton.textContent = 'Clear Cache';
  43. Object.assign(clearButton.style, {
  44. position: 'fixed',
  45. top: '10px',
  46. right: '110px',
  47. zIndex: 9999,
  48. padding: '6px',
  49. fontSize: '10px',
  50. backgroundColor: '#e0245e',
  51. color: 'white',
  52. border: 'none',
  53. borderRadius: '3px',
  54. cursor: 'pointer',
  55. });
  56. clearButton.onclick = () => {
  57. localStorage.removeItem(HASH_KEY);
  58. seenHashes = {};
  59. alert('Media cache cleared! Reload to see all items again.');
  60. };
  61.  
  62. document.body.appendChild(toggleButton);
  63. document.body.appendChild(clearButton);
  64.  
  65. // Generate visual hash from image or video
  66. function getVisualHash(el) {
  67. try {
  68. const canvas = document.createElement('canvas');
  69. canvas.width = canvas.height = 32;
  70. const ctx = canvas.getContext('2d');
  71. ctx.drawImage(el, 0, 0, 32, 32);
  72. return canvas.toDataURL().slice(0, 100);
  73. } catch {
  74. return null;
  75. }
  76. }
  77.  
  78. // Deduplication Logic
  79. function runDeduplication() {
  80. if (!dedupEnabled) return;
  81.  
  82. const mediaElements = document.querySelectorAll('img[src], video[src]');
  83. mediaElements.forEach(el => {
  84. if (!el.complete || el.naturalWidth === 0) return;
  85.  
  86. const hash = getVisualHash(el);
  87. if (!hash) return;
  88.  
  89. const container = el.closest('div[role="button"]') || el.closest('article');
  90. if (!container) return;
  91.  
  92. if (seenHashes[hash]) {
  93. container.style.setProperty('display', 'none', 'important');
  94. } else {
  95. seenHashes[hash] = true;
  96. localStorage.setItem(HASH_KEY, JSON.stringify(seenHashes));
  97. }
  98. });
  99. }
  100.  
  101. // Observe for lazy-loaded media
  102. const observer = new MutationObserver(() => runDeduplication());
  103. observer.observe(document.body, { childList: true, subtree: true });
  104.  
  105. window.addEventListener('load', () => setTimeout(runDeduplication, 3000));
  106. })();
  107. `
  108.  
Advertisement
Add Comment
Please, Sign In to add comment