Advertisement
Guest User

Untitled

a guest
Apr 7th, 2025
275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.46 KB | None | 0 0
  1. // ==UserScript==
  2. // @name /bag/ filter
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.7.6
  5. // @description Hides non whitelisted images. Images are whitelisted after 15 minutes of the post not being deleted.
  6. // @author Anonymous
  7. // @match https://boards.4chan.org/vg*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. // Check for a thread.
  15. if (!/^bag\/|\/bag\/|Blue Archive|BIue Archive/.test(document?.querySelector('.postInfo.desktop .subject')?.textContent?.trim() ?? '')) return;
  16.  
  17. const ADD_TO_WHITELIST_TIMEOUT_MS = 15 * 60 * 1000;
  18. const MD5_WHITELIST_KEY = 'bagFilter';
  19. const IS_DISABLED_KEY = 'bagFilterDisabled';
  20. const FILTERED_CSS_CLASS = 'bag-filter-filtered';
  21. const FILTER_STYLES = `
  22. .fileThumb img:not(.full-image).${FILTERED_CSS_CLASS} {
  23. width: 50px !important;
  24. height: 50px !important;
  25. filter: blur(5px) !important;
  26. }`;
  27.  
  28. const styleSheet = document.createElement('style');
  29. document.head.appendChild(styleSheet);
  30.  
  31. const opLinks = document.querySelector('.opContainer .fileText');
  32. const toggleLink = document.createElement('a');
  33. toggleLink.href = '#';
  34. opLinks.appendChild(document.createTextNode(' '));
  35. opLinks.appendChild(toggleLink);
  36. toggleLink.onclick = () => {
  37. window.localStorage.setItem(IS_DISABLED_KEY, String(!isDisabled()));
  38. updateToggle();
  39. }
  40.  
  41. function isDisabled() {
  42. return window.localStorage.getItem(IS_DISABLED_KEY) === 'true';
  43. }
  44.  
  45. function updateToggle() {
  46. if (isDisabled()) {
  47. toggleLink.textContent = 'enable bag filter';
  48. styleSheet.textContent = '';
  49. } else {
  50. toggleLink.textContent = 'disable bag filter';
  51. styleSheet.textContent = FILTER_STYLES;
  52. }
  53. }
  54.  
  55. const md5Whitelist = new Set(JSON.parse(window.localStorage.getItem(MD5_WHITELIST_KEY) || '[]'));
  56.  
  57. function update() {
  58. if (isDisabled()) {
  59. return;
  60. }
  61. const addToWhitelistPostTime = Date.now() - ADD_TO_WHITELIST_TIMEOUT_MS;
  62. const posts = document.querySelectorAll('.replyContainer:has(.fileThumb)');
  63. let md5WhitelistChanged = false;
  64. for (const post of posts) {
  65. const postTime = new Number(post.querySelector('.dateTime').dataset.utc) * 1000;
  66. const thumbnail = post.querySelector('img:not(.full-image');
  67. const md5 = thumbnail.dataset.md5;
  68. const otherFiltersMatch = imageSizeMatch(post);
  69. if (post.hasAttribute('hidden')) {
  70. if (md5Whitelist.has(md5)) {
  71. md5Whitelist.delete(md5);
  72. md5WhitelistChanged = true;
  73. }
  74. } else if (postTime < addToWhitelistPostTime && !post.classList.contains('deleted-post')) {
  75. if (!md5Whitelist.has(md5) && otherFiltersMatch) {
  76. md5Whitelist.add(md5);
  77. md5WhitelistChanged = true;
  78. }
  79. }
  80. if (md5Whitelist.has(md5) || !otherFiltersMatch) {
  81. thumbnail.classList.remove(FILTERED_CSS_CLASS);
  82. } else {
  83. thumbnail.classList.add(FILTERED_CSS_CLASS);
  84. }
  85. }
  86. if (md5WhitelistChanged) {
  87. window.localStorage.setItem(MD5_WHITELIST_KEY, JSON.stringify([...md5Whitelist]));
  88. }
  89. }
  90.  
  91. function imageSizeMatch(post) {
  92. const fileText = post.querySelector('.fileText-original, .fileText')?.textContent;
  93. if (fileText) {
  94. const matchInKB = fileText.match(/\((\d+(?:\.\d+)?)\s*KB/i);
  95. if (matchInKB) {
  96. const sizeInKB = parseFloat(matchInKB[1]);
  97. return sizeInKB >= 20;
  98. }
  99. const matchInMB = fileText.match(/\((\d+(?:\.\d+)?)\s*MB/i);
  100. if (matchInMB) {
  101. const sizeInMB = parseFloat(matchInMB[1]);
  102. return sizeInMB >= 1;
  103. }
  104. }
  105. return false;
  106. }
  107.  
  108. // Function to handle right-click with Shift key pressed to add the image to the whitelist
  109. function handleRightClick(event) {
  110. // Check if Shift key is pressed
  111. if (!event.shiftKey) return;
  112.  
  113. // Prevent the default context menu from showing
  114. event.preventDefault();
  115.  
  116. const thumbnail = event.target;
  117. const md5 = thumbnail.dataset.md5;
  118. if (md5 && !md5Whitelist.has(md5)) {
  119. md5Whitelist.add(md5);
  120. window.localStorage.setItem(MD5_WHITELIST_KEY, JSON.stringify([...md5Whitelist]));
  121. thumbnail.classList.remove(FILTERED_CSS_CLASS); // Immediately show the image
  122. }
  123. }
  124.  
  125. // Attach right-click event listeners to all image thumbnails
  126. function addRightClickListeners() {
  127. const images = document.querySelectorAll('.replyContainer .fileThumb img:not(.full-image)');
  128. images.forEach(image => {
  129. image.addEventListener('contextmenu', handleRightClick); // Detect right-click (context menu)
  130. });
  131. }
  132.  
  133. // Observe for dynamic content loading (e.g., infinite scrolling)
  134. const observer = new MutationObserver(() => {
  135. update();
  136. addRightClickListeners(); // Reattach listeners if new images are loaded
  137. });
  138.  
  139. observer.observe(document.body, {childList: true, subtree: true});
  140.  
  141. // Initial run
  142. updateToggle();
  143. update();
  144. addRightClickListeners();
  145. })();
  146.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement