Guest User

Untitled

a guest
Apr 23rd, 2025
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.19 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Hide Single-Post IDs
  3. // @namespace user-hide-single-posts
  4. // @version 1.3
  5. // @description Hides users with only one post. Unhides them when they post again. Includes toggle + live updates.
  6. // @match https://8chan.moe/*/res/*.html*
  7. // @match https://8chan.se/*/res/*.html*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (() => {
  12. const idNorm = s => (s.match(/^[0-9a-f]{6}/i) || [''])[0].toLowerCase();
  13. const QSA = (s, r = document) => [...r.querySelectorAll(s)];
  14.  
  15. const idUsageCountMap = new Map(); // ID → count
  16. const singlePostIdMap = new Map(); // ID → { postId }
  17.  
  18. const SETTINGS_KEY = 'hideSinglePostIDs';
  19. let hideEnabled = localStorage.getItem(SETTINGS_KEY) !== 'false';
  20.  
  21. function handlePost(post) {
  22. const idEl = post.querySelector('.labelId');
  23. if (!idEl) return;
  24.  
  25. const id = idNorm(idEl.textContent);
  26. if (!id) return;
  27.  
  28. const count = (idUsageCountMap.get(id) || 0) + 1;
  29. idUsageCountMap.set(id, count);
  30.  
  31. if (count === 1) {
  32. singlePostIdMap.set(id, { postId: post.id });
  33. if (hideEnabled) post.style.display = 'none';
  34. } else if (count === 2) {
  35. const firstPostId = singlePostIdMap.get(id)?.postId;
  36. const firstPost = document.getElementById(firstPostId);
  37. if (firstPost) firstPost.style.display = '';
  38. singlePostIdMap.delete(id);
  39. }
  40. }
  41.  
  42. function scanAllExistingPosts() {
  43. QSA('.postCell, .opCell').forEach(handlePost);
  44. }
  45.  
  46. function handleNewPosts(mutations) {
  47. for (const mutation of mutations) {
  48. for (const node of mutation.addedNodes) {
  49. if (!(node instanceof HTMLElement)) continue;
  50. if (node.matches('.postCell, .opCell')) {
  51. handlePost(node);
  52. } else {
  53. QSA('.postCell, .opCell', node).forEach(handlePost);
  54. }
  55. }
  56. }
  57. }
  58.  
  59. function toggleVisibility(enable) {
  60. hideEnabled = enable;
  61. localStorage.setItem(SETTINGS_KEY, enable);
  62.  
  63. for (const [id, { postId }] of singlePostIdMap.entries()) {
  64. const post = document.getElementById(postId);
  65. if (post) post.style.display = enable ? 'none' : '';
  66. }
  67. }
  68.  
  69. function createToggleUI() {
  70. const box = document.createElement('div');
  71. box.style = 'position:fixed;bottom:1rem;right:1rem;z-index:9999;background:#222;color:#fff;padding:6px;border-radius:6px;font:14px sans-serif';
  72. box.innerHTML = `<label><input type="checkbox" id="toggleHideIds"> Hide Single-Post IDs</label>`;
  73. document.body.appendChild(box);
  74.  
  75. const toggle = box.querySelector('#toggleHideIds');
  76. toggle.checked = hideEnabled;
  77. toggle.onchange = () => toggleVisibility(toggle.checked);
  78. }
  79.  
  80. function observeNewPosts() {
  81. const container = document.querySelector('.divPosts') || document.body;
  82. const observer = new MutationObserver(handleNewPosts);
  83. observer.observe(container, { childList: true, subtree: true });
  84. }
  85.  
  86. function waitForPostsAndInit() {
  87. if (document.querySelector('.postCell, .opCell')) {
  88. createToggleUI();
  89. scanAllExistingPosts();
  90. observeNewPosts();
  91. } else {
  92. requestAnimationFrame(waitForPostsAndInit);
  93. }
  94. }
  95.  
  96. waitForPostsAndInit();
  97. })();
  98.  
Advertisement
Add Comment
Please, Sign In to add comment